Skip to contentSkip to conversation

miscellaneous code improvements for sony-laptop

PATCH In review Marco Chiappero 2 participants 31 messages Sep 9, 2011 – Sep 13, 2011

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v2 cover miscellaneous code improvements for sony-laptop

Hello,

here is the first part of the V2 patches sent by me on the 3rd of June. As I have no spare time for coding at the moment, I have to split the previous patchset into two parts, I need more time for some patches while I have the first ones ready laying around. So these patches I'm sending include improvements to the current code and minor support extension, but no new features, that will come later in the second part. Note that patch numbers no longer match with the previous patchset that should be discarded, as is being totally replaced by this set and by the next one, available hopefully soon.

These patches are also available at
http://www.absence.it/vaio-acpi/source/patches/patchset-v2/

#1 lore raw

PATCH v2 1/14 sony-laptop: fix potential improper handle usage

SNC handles are positive numbers, all handles are valid with the sole exception of handle 0x0. This patch replaces int type with unsigned int when dealing with handles while sony_find_snc_handle now returns -1 when its value is 0x0.

---

drivers/platform/x86/sony-laptop.c +1 -1
@@ -150,7 +150,7 @@ enum sony_nc_rfkill {
 	N_SONY_RFKILL,
 };
 
-static int sony_rfkill_handle;
+static unsigned int sony_rfkill_handle;
 static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
 static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700,

0x900};
static void sony_nc_rfkill_update(void);
@@ -811,12 +811,12 @@ static int sony_nc_handles_cleanup(struc
return 0;
}

-static int sony_find_snc_handle(int handle) +static int sony_find_snc_handle(unsigned int handle)
{
int i;

- /* not initialized yet, return early */
- if (!handles)
+ /* not initialized yet or invalid handle, return early */
+ if (!handles || !handle)
return -1;

for (i = 0; i < 0x10; i++) {
@@ -830,7 +830,7 @@ static int sony_find_snc_handle(int hand
return -1;
}

-static int sony_call_snc_handle(int handle, int argument, int *result) +static int sony_call_snc_handle(unsigned int handle, int argument, int *result)
{
int ret = 0;
int offset = sony_find_snc_handle(handle);
@@ -937,7 +937,7 @@ static ssize_t sony_nc_sysfs_store(struc
*/
struct sony_backlight_props {
struct backlight_device *dev;
- int handle;
+ unsigned int handle;
u8 offset;
u8 maxlvl;
};
@@ -1557,7 +1557,7 @@ static void sony_nc_kbd_backlight_resume
&ignore);
}

-static void sony_nc_backlight_ng_read_limits(int handle, +static void sony_nc_backlight_ng_read_limits(unsigned int handle,
struct sony_backlight_props *props)
{
int offset;

#2 lore raw

PATCH RESEND v2 1/14 sony-laptop: fix potential improper handle usage

In reply to Marco Chiappero

SNC handles are positive numbers, all handles are valid with the sole exception of handle 0x0. This patch replaces int type with unsigned int when dealing with handles while sony_find_snc_handle now returns -1 when its value is 0x0.

---

drivers/platform/x86/sony-laptop.c +7 -7
@@ -150,7 +150,7 @@ enum sony_nc_rfkill {
 	N_SONY_RFKILL,
 };
 
-static int sony_rfkill_handle;
+static unsigned int sony_rfkill_handle;
 static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
 static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
 static void sony_nc_rfkill_update(void);
@@ -811,12 +811,12 @@ static int sony_nc_handles_cleanup(struc
 	return 0;
 }
 
-static int sony_find_snc_handle(int handle)
+static int sony_find_snc_handle(unsigned int handle)
 {
 	int i;
 
-	/* not initialized yet, return early */
-	if (!handles)
+	/* not initialized yet or invalid handle, return early */
+	if (!handles || !handle)
 		return -1;
 
 	for (i = 0; i < 0x10; i++) {
@@ -830,7 +830,7 @@ static int sony_find_snc_handle(int hand
 	return -1;
 }
 
-static int sony_call_snc_handle(int handle, int argument, int *result)
+static int sony_call_snc_handle(unsigned int handle, int argument, int *result)
 {
 	int ret = 0;
 	int offset = sony_find_snc_handle(handle);
@@ -937,7 +937,7 @@ static ssize_t sony_nc_sysfs_store(struc
  */
 struct sony_backlight_props {
 	struct backlight_device *dev;
-	int			handle;
+	unsigned int		handle;
 	u8			offset;
 	u8			maxlvl;
 };
@@ -1557,7 +1557,7 @@ static void sony_nc_kbd_backlight_resume
 				&ignore);
 }
 
-static void sony_nc_backlight_ng_read_limits(int handle,
+static void sony_nc_backlight_ng_read_limits(unsigned int handle,
 		struct sony_backlight_props *props)
 {
 	int offset;
#3 lore raw

PATCH v2 2/14 sony-laptop: use usigned data type when calling ACPI methods

In reply to Marco Chiappero

Data exchanges with the SNC device should use unsigned data types: to avoid any implicit cast, this patch removes any int usage in favor of unsigned int or u32.

---

drivers/platform/x86/sony-laptop.c +0 -1
@@ -689,7 +689,8 @@ static struct acpi_device *sony_nc_acpi_
 /*
  * acpi_evaluate_object wrappers
  */
-static int acpi_callgetfunc(acpi_handle handle, char *name, int

*result)
+static int acpi_callgetfunc(acpi_handle handle, char *name,
+ unsigned int *result)
{
struct acpi_buffer output;
union acpi_object out_obj;
@@ -709,8 +710,8 @@ static int acpi_callgetfunc(acpi_handle
return -1;
}

-static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
- int *result)
+static int acpi_callsetfunc(acpi_handle handle, char *name, u32 value,
+ unsigned int *result)
{
struct acpi_object_list params;
union acpi_object in_obj;
@@ -767,8 +768,7 @@ static ssize_t sony_nc_handles_show(stru

static int sony_nc_handles_setup(struct platform_device *pd) {
- int i;
- int result;
+ unsigned int i, result;

handles = kzalloc(sizeof(*handles), GFP_KERNEL); if (!handles)
@@ -830,7 +830,9 @@ static int sony_find_snc_handle(unsigned
return -1;
}

-static int sony_call_snc_handle(unsigned int handle, int argument, int *result)
+/* call command method SN07, accepts a 32 bit integer, returns a integer */
+static int sony_call_snc_handle(unsigned int handle, unsigned int argument,
+ unsigned int *result)
{
int ret = 0;
int offset = sony_find_snc_handle(handle);
@@ -838,6 +840,7 @@ static int sony_call_snc_handle(unsigned
if (offset < 0)
return -1;

+ /* max 32 bit wide argument, for wider input use SN06 */
ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
result);
dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset |
argument,
@@ -886,7 +889,7 @@ static int boolean_validate(const int di
static ssize_t sony_nc_sysfs_show(struct device *dev, struct
device_attribute *attr,
char *buffer)
{
- int value;
+ unsigned int value;
struct sony_nc_value *item =
container_of(attr, struct sony_nc_value, devattr);

@@ -906,7 +909,7 @@ static ssize_t sony_nc_sysfs_store(struc
struct device_attribute *attr, const char *buffer, size_t count)
{
- int value;
+ unsigned long value;
struct sony_nc_value *item =
container_of(attr, struct sony_nc_value, devattr);

@@ -951,7 +954,7 @@ static int sony_backlight_update_status(

static int sony_backlight_get_brightness(struct backlight_device *bd) {
- int value;
+ unsigned int value;

if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
return 0;
@@ -961,7 +964,7 @@ static int sony_backlight_get_brightness

static int sony_nc_get_brightness_ng(struct backlight_device *bd) {
- int result;
+ unsigned int result;
struct sony_backlight_props *sdev =
(struct sony_backlight_props *)bl_get_data(bd);

@@ -972,7 +975,7 @@ static int sony_nc_get_brightness_ng(str

static int sony_nc_update_status_ng(struct backlight_device *bd) {
- int value, result;
+ unsigned int value, result;
struct sony_backlight_props *sdev =
(struct sony_backlight_props *)bl_get_data(bd);

@@ -1069,7 +1072,7 @@ static void sony_nc_notify(struct acpi_d

if (ev >= 0x90) {
/* New-style event */
- int result;
+ unsigned int result;
int key_handle = 0;
ev -= 0x90;

@@ -1139,7 +1142,7 @@ static acpi_status sony_walk_callback(ac
*/
static int sony_nc_function_setup(struct acpi_device *device) {
- int result;
+ unsigned int result;

/* Enable all events */ acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
@@ -1206,8 +1209,8 @@ static void sony_nc_rfkill_cleanup(void)

static int sony_nc_rfkill_set(void *data, bool blocked) {
- int result;
- int argument = sony_rfkill_address[(long) data] + 0x100;
+ unsigned int result;
+ unsigned int argument = sony_rfkill_address[(long) data] + 0x100;

if (!blocked)
argument |= 0xff0000;
@@ -1226,7 +1229,7 @@ static int sony_nc_setup_rfkill(struct a
struct rfkill *rfk;
enum rfkill_type type;
const char *name;
- int result;
+ unsigned int result;
bool hwblock;

switch (nc_type) {
@@ -1271,14 +1274,14 @@ static int sony_nc_setup_rfkill(struct a
static void sony_nc_rfkill_update(void)
{
enum sony_nc_rfkill i;
- int result;
+ unsigned int result;
bool hwblock;

sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); hwblock = !(result & 0x1);

for (i = 0; i < N_SONY_RFKILL; i++) {
- int argument = sony_rfkill_address[i];
+ unsigned int argument = sony_rfkill_address[i];

if (!sony_rfkill_devices[i])
continue;
@@ -1390,7 +1393,7 @@ static struct kbd_backlight *kbdbl_handl

static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) {
- int result;
+ unsigned int result;

if (value > 1)
return -EINVAL;
@@ -1438,7 +1441,7 @@ static ssize_t sony_nc_kbd_backlight_mod

static int __sony_nc_kbd_backlight_timeout_set(u8 value) {
- int result;
+ unsigned int result;

if (value > 3)
return -EINVAL;
@@ -1482,7 +1485,7 @@ static ssize_t sony_nc_kbd_backlight_tim

static int sony_nc_kbd_backlight_setup(struct platform_device *pd) {
- int result;
+ unsigned int result;

if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
return 0;
@@ -1527,7 +1530,7 @@ outkzalloc:
static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) {
if (kbdbl_handle) {
- int result;
+ unsigned int result;

device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
@@ -1543,7 +1546,7 @@ static int sony_nc_kbd_backlight_cleanup

static void sony_nc_kbd_backlight_resume(void)
{
- int ignore = 0;
+ unsigned int ignore = 0;

if (!kbdbl_handle)
return;
@@ -2659,7 +2662,7 @@ static long sonypi_misc_ioctl(struct fil
void __user *argp = (void __user *)arg;
u8 val8;
u16 val16;
- int value;
+ unsigned int value;

mutex_lock(&spic_dev.lock);
switch (cmd) {

#4 lore raw

PATCH RESEND v2 2/14 sony-laptop: use usigned data type when calling ACPI methods

In reply to Marco Chiappero

Data exchanges with the SNC device should use unsigned data types: to avoid any implicit cast, this patch removes any int usage in favor of unsigned int or u32.

---

drivers/platform/x86/sony-laptop.c +27 -24
@@ -689,7 +689,8 @@ static struct acpi_device *sony_nc_acpi_
 /*
  * acpi_evaluate_object wrappers
  */
-static int acpi_callgetfunc(acpi_handle handle, char *name, int *result)
+static int acpi_callgetfunc(acpi_handle handle, char *name,
+				unsigned int *result)
 {
 	struct acpi_buffer output;
 	union acpi_object out_obj;
@@ -709,8 +710,8 @@ static int acpi_callgetfunc(acpi_handle 
 	return -1;
 }
 
-static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
-			    int *result)
+static int acpi_callsetfunc(acpi_handle handle, char *name, u32 value,
+				unsigned int *result)
 {
 	struct acpi_object_list params;
 	union acpi_object in_obj;
@@ -767,8 +768,7 @@ static ssize_t sony_nc_handles_show(stru
 
 static int sony_nc_handles_setup(struct platform_device *pd)
 {
-	int i;
-	int result;
+	unsigned int i, result;
 
 	handles = kzalloc(sizeof(*handles), GFP_KERNEL);
 	if (!handles)
@@ -830,7 +830,9 @@ static int sony_find_snc_handle(unsigned
 	return -1;
 }
 
-static int sony_call_snc_handle(unsigned int handle, int argument, int *result)
+/* call command method SN07, accepts a 32 bit integer, returns a integer */
+static int sony_call_snc_handle(unsigned int handle, unsigned int argument,
+				unsigned int *result)
 {
 	int ret = 0;
 	int offset = sony_find_snc_handle(handle);
@@ -838,6 +840,7 @@ static int sony_call_snc_handle(unsigned
 	if (offset < 0)
 		return -1;
 
+	/* max 32 bit wide argument, for wider input use SN06 */
 	ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
 			result);
 	dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument,
@@ -886,7 +889,7 @@ static int boolean_validate(const int di
 static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
 			      char *buffer)
 {
-	int value;
+	unsigned int value;
 	struct sony_nc_value *item =
 	    container_of(attr, struct sony_nc_value, devattr);
 
@@ -906,7 +909,7 @@ static ssize_t sony_nc_sysfs_store(struc
 			       struct device_attribute *attr,
 			       const char *buffer, size_t count)
 {
-	int value;
+	unsigned long value;
 	struct sony_nc_value *item =
 	    container_of(attr, struct sony_nc_value, devattr);
 
@@ -951,7 +954,7 @@ static int sony_backlight_update_status(
 
 static int sony_backlight_get_brightness(struct backlight_device *bd)
 {
-	int value;
+	unsigned int value;
 
 	if (acpi_callgetfunc(sony_nc_acpi_handle, "GBRT", &value))
 		return 0;
@@ -961,7 +964,7 @@ static int sony_backlight_get_brightness
 
 static int sony_nc_get_brightness_ng(struct backlight_device *bd)
 {
-	int result;
+	unsigned int result;
 	struct sony_backlight_props *sdev =
 		(struct sony_backlight_props *)bl_get_data(bd);
 
@@ -972,7 +975,7 @@ static int sony_nc_get_brightness_ng(str
 
 static int sony_nc_update_status_ng(struct backlight_device *bd)
 {
-	int value, result;
+	unsigned int value, result;
 	struct sony_backlight_props *sdev =
 		(struct sony_backlight_props *)bl_get_data(bd);
 
@@ -1069,7 +1072,7 @@ static void sony_nc_notify(struct acpi_d
 
 	if (ev >= 0x90) {
 		/* New-style event */
-		int result;
+		unsigned int result;
 		int key_handle = 0;
 		ev -= 0x90;
 
@@ -1139,7 +1142,7 @@ static acpi_status sony_walk_callback(ac
  */
 static int sony_nc_function_setup(struct acpi_device *device)
 {
-	int result;
+	unsigned int result;
 
 	/* Enable all events */
 	acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
@@ -1206,8 +1209,8 @@ static void sony_nc_rfkill_cleanup(void)
 
 static int sony_nc_rfkill_set(void *data, bool blocked)
 {
-	int result;
-	int argument = sony_rfkill_address[(long) data] + 0x100;
+	unsigned int result;
+	unsigned int argument = sony_rfkill_address[(long) data] + 0x100;
 
 	if (!blocked)
 		argument |= 0xff0000;
@@ -1226,7 +1229,7 @@ static int sony_nc_setup_rfkill(struct a
 	struct rfkill *rfk;
 	enum rfkill_type type;
 	const char *name;
-	int result;
+	unsigned int result;
 	bool hwblock;
 
 	switch (nc_type) {
@@ -1271,14 +1274,14 @@ static int sony_nc_setup_rfkill(struct a
 static void sony_nc_rfkill_update(void)
 {
 	enum sony_nc_rfkill i;
-	int result;
+	unsigned int result;
 	bool hwblock;
 
 	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
 	hwblock = !(result & 0x1);
 
 	for (i = 0; i < N_SONY_RFKILL; i++) {
-		int argument = sony_rfkill_address[i];
+		unsigned int argument = sony_rfkill_address[i];
 
 		if (!sony_rfkill_devices[i])
 			continue;
@@ -1390,7 +1393,7 @@ static struct kbd_backlight *kbdbl_handl
 
 static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
 {
-	int result;
+	unsigned int result;
 
 	if (value > 1)
 		return -EINVAL;
@@ -1438,7 +1441,7 @@ static ssize_t sony_nc_kbd_backlight_mod
 
 static int __sony_nc_kbd_backlight_timeout_set(u8 value)
 {
-	int result;
+	unsigned int result;
 
 	if (value > 3)
 		return -EINVAL;
@@ -1482,7 +1485,7 @@ static ssize_t sony_nc_kbd_backlight_tim
 
 static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
 {
-	int result;
+	unsigned int result;
 
 	if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
 		return 0;
@@ -1527,7 +1530,7 @@ outkzalloc:
 static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
 {
 	if (kbdbl_handle) {
-		int result;
+		unsigned int result;
 
 		device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
 		device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
@@ -1543,7 +1546,7 @@ static int sony_nc_kbd_backlight_cleanup
 
 static void sony_nc_kbd_backlight_resume(void)
 {
-	int ignore = 0;
+	unsigned int ignore = 0;
 
 	if (!kbdbl_handle)
 		return;
@@ -2659,7 +2662,7 @@ static long sonypi_misc_ioctl(struct fil
 	void __user *argp = (void __user *)arg;
 	u8 val8;
 	u16 val16;
-	int value;
+	unsigned int value;
 
 	mutex_lock(&spic_dev.lock);
 	switch (cmd) {
#5 lore raw

PATCH v2 3/14 sony-laptop: replace simple_strtoul with strict_strtoul

In reply to Marco Chiappero

Any occurrence of simple_strtoul has been replaced with the better strict_strtoul, because the former accepts and ignores any char at the tail while the latter only accepts a new line character following the number (and -EINVAL is returned otherwise).

---

drivers/platform/x86/sony-laptop.c +11 -4
@@ -919,7 +919,8 @@ static ssize_t sony_nc_sysfs_store(struc
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
 
 	if (item->validate)
 		value = item->validate(SNC_VALIDATE_IN, value);
@@ -2437,7 +2438,9 @@ static ssize_t sony_pic_wwanpower_store(
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
 	mutex_lock(&spic_dev.lock);
 	__sony_pic_set_wwanpower(value);
 	mutex_unlock(&spic_dev.lock);
@@ -2474,7 +2477,9 @@ static ssize_t sony_pic_bluetoothpower_s
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
 	mutex_lock(&spic_dev.lock);
 	__sony_pic_set_bluetoothpower(value);
 	mutex_unlock(&spic_dev.lock);
@@ -2513,7 +2518,9 @@ static ssize_t sony_pic_fanspeed_store(s
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
 	if (sony_pic_set_fanspeed(value))
 		return -EIO;
 
#6 lore raw

PATCH RESEND v2 3/14 sony-laptop: replace simple_strtoul with strict_strtoul

In reply to Marco Chiappero

Any occurrence of simple_strtoul has been replaced with the better strict_strtoul, because the former accepts and ignores any char at the tail while the latter only accepts a new line character following the number (and -EINVAL is returned otherwise).

---

drivers/platform/x86/sony-laptop.c +11 -4
@@ -919,7 +919,8 @@ static ssize_t sony_nc_sysfs_store(struc
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
 
 	if (item->validate)
 		value = item->validate(SNC_VALIDATE_IN, value);
@@ -2437,7 +2438,9 @@ static ssize_t sony_pic_wwanpower_store(
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
 	mutex_lock(&spic_dev.lock);
 	__sony_pic_set_wwanpower(value);
 	mutex_unlock(&spic_dev.lock);
@@ -2474,7 +2477,9 @@ static ssize_t sony_pic_bluetoothpower_s
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
 	mutex_lock(&spic_dev.lock);
 	__sony_pic_set_bluetoothpower(value);
 	mutex_unlock(&spic_dev.lock);
@@ -2513,7 +2518,9 @@ static ssize_t sony_pic_fanspeed_store(s
 	if (count > 31)
 		return -EINVAL;
 
-	value = simple_strtoul(buffer, NULL, 10);
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
 	if (sony_pic_set_fanspeed(value))
 		return -EIO;
 
#7 lore raw

PATCH v2 4/14 sony-laptop: add new ACPI SN06 method helper functions

In reply to Marco Chiappero

SN06 method related code moved from sony_nc_rfkill_setup to acpi_callsetfunc_buffer; a new helper sony_call_snc_handle_buffer is added too, to be used by different handles that need it and not just the rfkill handles.

---

drivers/platform/x86/sony-laptop.c +15 -0
@@ -744,6 +744,72 @@ static int acpi_callsetfunc(acpi_handle 
 	return -1;
 }
 
+static int acpi_callsetfunc_buffer(acpi_handle handle, u64 value,
+					u8 array[], unsigned int size)
+{
+	u8 buffer[sizeof(value)];
+	int length = -1;
+	struct acpi_object_list params;
+	union acpi_object in_obj;
+	union acpi_object *values;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_status status;
+
+	if (!array || !size)
+		return length;
+
+	/* use a buffer type as parameter to overcome any 32 bits ACPI limit

*/
+ memcpy(buffer, &value, sizeof(buffer));
+
+ params.count = 1;
+ params.pointer = &in_obj;
+ in_obj.type = ACPI_TYPE_BUFFER;
+ in_obj.buffer.length = sizeof(buffer);
+ in_obj.buffer.pointer = buffer;
+
+ /* since SN06 is the only known method returning a buffer we
+ * can hard code it, it is not necessary to have a parameter
+ */
+ status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
+ &output);
+ values = (union acpi_object *) output.pointer;
+ if (ACPI_FAILURE(status) || !values) {
+ dprintk("acpi_evaluate_object failed\n");
+ goto error;
+ }
+
+ /* some buggy DSDTs return integer when the output does
+ not execede the 4 bytes size
+ */
+ if (values->type == ACPI_TYPE_BUFFER) {
+ if (values->buffer.length <= 0)
+ goto error;
+
+ length = size > values->buffer.length ?
+ values->buffer.length : size;
+
+ memcpy(array, values->buffer.pointer, length);
+ } else if (values->type == ACPI_TYPE_INTEGER) {
+ u32 result = values->integer.value;
+ if (size < 4)
+ goto error;
+
+ length = 0;
+ while (length != 4) {
+ array[length] = result & 0xff;
+ result >>= 8;
+ length++;
+ }
+ } else {
+ pr_err("Invalid return object 0x%.2x\n", values->type);
+ goto error;
+ }
+
+error:
+ kfree(output.pointer);
+ return length;
+}
+
struct sony_nc_handles {
u16 cap[0x10];
struct device_attribute devattr;
@@ -848,6 +914,24 @@ static int sony_call_snc_handle(unsigned
return ret;
}

+/* call command method SN06, accepts a wide input buffer, returns a buffer */
+static int sony_call_snc_handle_buffer(unsigned int handle, u64 argument,
+ u8 result[], unsigned int size)
+{
+ int ret = 0;
+ int offset = sony_find_snc_handle(handle);
+
+ if (offset < 0)
+ return -1;
+
+ ret = acpi_callsetfunc_buffer(sony_nc_acpi_handle,
+ offset | argument, result, size);
+ dprintk("called SN06 with 0x%.4llx (%u bytes read)\n",
+ offset | argument, ret);
+
+ return ret;
+}
+
/*
* sony_nc_values input/output validate functions
*/
@@ -1300,21 +1384,17 @@ static void sony_nc_rfkill_update(void)
}
}

-static void sony_nc_rfkill_setup(struct acpi_device *device) +static int sony_nc_rfkill_setup(struct acpi_device *device)
{
+#define RFKILL_BUFF_SIZE 8
+ u8 dev_code, i, buff[RFKILL_BUFF_SIZE] = { 0 };
int offset;
- u8 dev_code, i;
- acpi_status status;
- struct acpi_object_list params;
- union acpi_object in_obj;
- union acpi_object *device_enum;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

offset = sony_find_snc_handle(0x124);
if (offset == -1) {
offset = sony_find_snc_handle(0x135);
if (offset == -1)
- return;
+ return 0;
else
sony_rfkill_handle = 0x135;
} else
@@ -1324,34 +1404,16 @@ static void sony_nc_rfkill_setup(struct
/* need to read the whole buffer returned by the acpi call to SN06
* here otherwise we may miss some features
*/
- params.count = 1;
- params.pointer = &in_obj;
- in_obj.type = ACPI_TYPE_INTEGER;
- in_obj.integer.value = offset;
- status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
- &buffer);
- if (ACPI_FAILURE(status)) {
- dprintk("Radio device enumeration failed\n");
- return;
- }
-
- device_enum = (union acpi_object *) buffer.pointer;
- if (!device_enum) {
- pr_err("No SN06 return object\n");
- goto out_no_enum;
- }
- if (device_enum->type != ACPI_TYPE_BUFFER) {
- pr_err("Invalid SN06 return object 0x%.2x\n",
- device_enum->type);
- goto out_no_enum;
- }
+ if (sony_call_snc_handle_buffer(sony_rfkill_handle, 0x000,
+ buff, RFKILL_BUFF_SIZE) < 0)
+ return -EIO;

/* the buffer is filled with magic numbers describing the devices
* available, 0xff terminates the enumeration
*/
- for (i = 0; i < device_enum->buffer.length; i++) {
+ for (i = 0; i < RFKILL_BUFF_SIZE; i++) {

- dev_code = *(device_enum->buffer.pointer + i);
+ dev_code = buff[i];
if (dev_code == 0xff)
break;

@@ -1371,9 +1433,7 @@ static void sony_nc_rfkill_setup(struct
sony_nc_setup_rfkill(device, SONY_WIMAX);
}

-out_no_enum:
- kfree(buffer.pointer);
- return;
+ return 0;
}

/* Keyboard backlight feature */

#8 lore raw

PATCH RESEND v2 4/14 sony-laptop: add new ACPI SN06 method helper functions

In reply to Marco Chiappero

SN06 method related code moved from sony_nc_rfkill_setup to acpi_callsetfunc_buffer; a new helper sony_call_snc_handle_buffer is added too, to be used by different handles that need it and not just the rfkill handles.

---

drivers/platform/x86/sony-laptop.c +94 -34
@@ -744,6 +744,72 @@ static int acpi_callsetfunc(acpi_handle 
 	return -1;
 }
 
+static int acpi_callsetfunc_buffer(acpi_handle handle, u64 value,
+					u8 array[], unsigned int size)
+{
+	u8 buffer[sizeof(value)];
+	int length = -1;
+	struct acpi_object_list params;
+	union acpi_object in_obj;
+	union acpi_object *values;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_status status;
+
+	if (!array || !size)
+		return length;
+
+	/* use a buffer type as parameter to overcome any 32 bits ACPI limit */
+	memcpy(buffer, &value, sizeof(buffer));
+
+	params.count = 1;
+	params.pointer = &in_obj;
+	in_obj.type = ACPI_TYPE_BUFFER;
+	in_obj.buffer.length = sizeof(buffer);
+	in_obj.buffer.pointer = buffer;
+
+	/* since SN06 is the only known method returning a buffer we
+	 * can hard code it, it is not necessary to have a parameter
+	 */
+	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
+			&output);
+	values = (union acpi_object *) output.pointer;
+	if (ACPI_FAILURE(status) || !values) {
+		dprintk("acpi_evaluate_object failed\n");
+		goto error;
+	}
+
+	/* some buggy DSDTs return integer when the output does
+	   not execede the 4 bytes size
+	*/
+	if (values->type == ACPI_TYPE_BUFFER) {
+		if (values->buffer.length <= 0)
+			goto error;
+
+		length = size > values->buffer.length ?
+			values->buffer.length : size;
+
+		memcpy(array, values->buffer.pointer, length);
+	} else if (values->type == ACPI_TYPE_INTEGER) {
+		u32 result = values->integer.value;
+		if (size < 4)
+			goto error;
+
+		length = 0;
+		while (length != 4) {
+			array[length] = result & 0xff;
+			result >>= 8;
+			length++;
+		}
+	} else {
+		pr_err("Invalid return object 0x%.2x\n", values->type);
+		goto error;
+	}
+
+error:
+	kfree(output.pointer);
+	return length;
+}
+
 struct sony_nc_handles {
 	u16 cap[0x10];
 	struct device_attribute devattr;
@@ -848,6 +914,24 @@ static int sony_call_snc_handle(unsigned
 	return ret;
 }
 
+/* call command method SN06, accepts a wide input buffer, returns a buffer */
+static int sony_call_snc_handle_buffer(unsigned int handle, u64 argument,
+					u8 result[], unsigned int size)
+{
+	int ret = 0;
+	int offset = sony_find_snc_handle(handle);
+
+	if (offset < 0)
+		return -1;
+
+	ret = acpi_callsetfunc_buffer(sony_nc_acpi_handle,
+			offset | argument, result, size);
+	dprintk("called SN06 with 0x%.4llx (%u bytes read)\n",
+			offset | argument, ret);
+
+	return ret;
+}
+
 /*
  * sony_nc_values input/output validate functions
  */
@@ -1300,21 +1384,17 @@ static void sony_nc_rfkill_update(void)
 	}
 }
 
-static void sony_nc_rfkill_setup(struct acpi_device *device)
+static int sony_nc_rfkill_setup(struct acpi_device *device)
 {
+#define	RFKILL_BUFF_SIZE 8
+	u8 dev_code, i, buff[RFKILL_BUFF_SIZE] = { 0 };
 	int offset;
-	u8 dev_code, i;
-	acpi_status status;
-	struct acpi_object_list params;
-	union acpi_object in_obj;
-	union acpi_object *device_enum;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
 	offset = sony_find_snc_handle(0x124);
 	if (offset == -1) {
 		offset = sony_find_snc_handle(0x135);
 		if (offset == -1)
-			return;
+			return 0;
 		else
 			sony_rfkill_handle = 0x135;
 	} else
@@ -1324,34 +1404,16 @@ static void sony_nc_rfkill_setup(struct 
 	/* need to read the whole buffer returned by the acpi call to SN06
 	 * here otherwise we may miss some features
 	 */
-	params.count = 1;
-	params.pointer = &in_obj;
-	in_obj.type = ACPI_TYPE_INTEGER;
-	in_obj.integer.value = offset;
-	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
-			&buffer);
-	if (ACPI_FAILURE(status)) {
-		dprintk("Radio device enumeration failed\n");
-		return;
-	}
-
-	device_enum = (union acpi_object *) buffer.pointer;
-	if (!device_enum) {
-		pr_err("No SN06 return object\n");
-		goto out_no_enum;
-	}
-	if (device_enum->type != ACPI_TYPE_BUFFER) {
-		pr_err("Invalid SN06 return object 0x%.2x\n",
-		       device_enum->type);
-		goto out_no_enum;
-	}
+	if (sony_call_snc_handle_buffer(sony_rfkill_handle, 0x000,
+					buff, RFKILL_BUFF_SIZE) < 0)
+		return -EIO;
 
 	/* the buffer is filled with magic numbers describing the devices
 	 * available, 0xff terminates the enumeration
 	 */
-	for (i = 0; i < device_enum->buffer.length; i++) {
+	for (i = 0; i < RFKILL_BUFF_SIZE; i++) {
 
-		dev_code = *(device_enum->buffer.pointer + i);
+		dev_code = buff[i];
 		if (dev_code == 0xff)
 			break;
 
@@ -1371,9 +1433,7 @@ static void sony_nc_rfkill_setup(struct 
 			sony_nc_setup_rfkill(device, SONY_WIMAX);
 	}
 
-out_no_enum:
-	kfree(buffer.pointer);
-	return;
+	return 0;
 }
 
 /* Keyboard backlight feature */
#9 lore raw

PATCH v2 5/14 sony-laptop: new SNC setup and cleanup functions

In reply to Marco Chiappero

New SNC handles setup and cleanup functions, sony_nc_handles_setup and sony_nc_handles_cleanup. They avoid eccessive tainting of sony_nc_add and sony_nc_remove, with cleaner and easier to read code, better event initialization and better error handling. Due to name collision, the previously defined functions related to the handle list has been renamed sony_nc_handles_list_setup and sony_nc_handles_list_show.

---

drivers/platform/x86/sony-laptop.c +97 -19
@@ -810,14 +810,14 @@ error:
 	return length;
 }
 
-struct sony_nc_handles {
+struct sony_nc_handles_list {
 	u16 cap[0x10];
 	struct device_attribute devattr;
 };
 
-static struct sony_nc_handles *handles;
+static struct sony_nc_handles_list *handles;
 
-static ssize_t sony_nc_handles_show(struct device *dev,
+static ssize_t sony_nc_handles_list_show(struct device *dev,
 		struct device_attribute *attr, char *buffer)
 {
 	ssize_t len = 0;
@@ -832,7 +832,7 @@ static ssize_t sony_nc_handles_show(stru
 	return len;
 }
 
-static int sony_nc_handles_setup(struct platform_device *pd)
+static int sony_nc_handles_list_setup(struct platform_device *pd)
 {
 	unsigned int i, result;
 
@@ -853,7 +853,7 @@ static int sony_nc_handles_setup(struct 
 		sysfs_attr_init(&handles->devattr.attr);
 		handles->devattr.attr.name = "handles";
 		handles->devattr.attr.mode = S_IRUGO;
-		handles->devattr.show = sony_nc_handles_show;
+		handles->devattr.show = sony_nc_handles_list_show;
 
 		/* allow reading capabilities via sysfs */
 		if (device_create_file(&pd->dev, &handles->devattr)) {
@@ -866,7 +866,7 @@ static int sony_nc_handles_setup(struct 
 	return 0;
 }
 
-static int sony_nc_handles_cleanup(struct platform_device *pd)
+static int sony_nc_handles_list_cleanup(struct platform_device *pd)
 {
 	if (handles) {
 		if (debug)
@@ -1736,6 +1736,94 @@ static void sony_nc_backlight_cleanup(vo
 		backlight_device_unregister(sony_bl_props.dev);
 }
 
+static int sony_nc_handles_setup(struct platform_device *pd)
+{
+	unsigned int i, bitmask, result;
+	int ret;
+
+	/* retrieve the implemented offsets mask */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN00", 0x10, &bitmask))
+		return -EIO;
+
+	/* retrieve the available handles, otherwise return */
+	ret = sony_nc_handles_list_setup(pd);
+	if (ret)
+		return ret;
+
+	/* setup found handles here */
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+		int unsigned handle = handles->cap[i];
+
+		if (!handle)
+			continue;
+
+		dprintk("looking at handle 0x%.4x\n", handle);
+
+		switch (handle) {
+		case 0x0137:
+			ret = sony_nc_kbd_backlight_setup(pd);
+		case 0x0124:
+		case 0x0135:
+			ret = sony_nc_rfkill_setup(sony_nc_acpi_device);
+			break;
+		default:
+			continue;
+		}
+
+		if (ret < 0)
+			pr_warn("handle 0x%.4x setup failed (ret: %i)",
+								handle, ret);
+		else
+			dprintk("handle 0x%.4x setup completed\n", handle);
+	}
+
+	/* Enable all events for the found handles, otherwise return */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", bitmask, &result))
+		return -EIO;
+
+	return 0;
+}
+
+static int sony_nc_handles_cleanup(struct platform_device *pd)
+{
+	unsigned int i, result, bitmask;
+
+	/* retrieve the event enabled handles */
+	acpi_callgetfunc(sony_nc_acpi_handle, "SN01", &bitmask);
+
+	/* disable the event generation	for every handle */
+	acpi_callsetfunc(sony_nc_acpi_handle, "SN03", bitmask, &result);
+
+	/* cleanup handles here */
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+
+		int unsigned handle = handles->cap[i];
+
+		if (!handle)
+			continue;
+
+		dprintk("looking at handle 0x%.4x\n", handle);
+
+		switch (handle) {
+		case 0x0137:
+			sony_nc_kbd_backlight_cleanup(pd);
+		case 0x0124:
+		case 0x0135:
+			sony_nc_rfkill_cleanup();
+			break;
+		default:
+			continue;
+		}
+
+		dprintk("handle 0x%.4x deconfigured\n", handle);
+	}
+
+	/* finally cleanup the handles list */
+	sony_nc_handles_list_cleanup(pd);
+
+	return 0;
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
@@ -1783,21 +1871,17 @@ static int sony_nc_add(struct acpi_devic
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
 					 &handle))) {
 		dprintk("Doing SNC setup\n");
+		sony_nc_function_setup(device);
 		result = sony_nc_handles_setup(sony_pf_device);
 		if (result)
-			goto outpresent;
-		result = sony_nc_kbd_backlight_setup(sony_pf_device);
-		if (result)
 			goto outsnc;
-		sony_nc_function_setup(device);
-		sony_nc_rfkill_setup(device);
 	}
 
 	/* setup input devices and helper fifo */
 	result = sony_laptop_setup_input(device);
 	if (result) {
 		pr_err("Unable to create input devices\n");
-		goto outkbdbacklight;
+		goto outsnc;
 	}
 
 	if (acpi_video_backlight_support()) {
@@ -1855,9 +1939,6 @@ static int sony_nc_add(struct acpi_devic
 
 	sony_laptop_remove_input();
 
-      outkbdbacklight:
-	sony_nc_kbd_backlight_cleanup(sony_pf_device);
-
       outsnc:
 	sony_nc_handles_cleanup(sony_pf_device);
 
@@ -1865,7 +1946,6 @@ static int sony_nc_add(struct acpi_devic
 	sony_pf_remove();
 
       outwalk:
-	sony_nc_rfkill_cleanup();
 	return result;
 }
 
@@ -1874,6 +1954,7 @@ static int sony_nc_remove(struct acpi_de
 	struct sony_nc_value *item;
 
 	sony_nc_backlight_cleanup();
+	sony_nc_handles_cleanup(sony_pf_device);
 
 	sony_nc_acpi_device = NULL;
 
@@ -1881,11 +1962,8 @@ static int sony_nc_remove(struct acpi_de
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
 	}
 
-	sony_nc_kbd_backlight_cleanup(sony_pf_device);
-	sony_nc_handles_cleanup(sony_pf_device);
 	sony_pf_remove();
 	sony_laptop_remove_input();
-	sony_nc_rfkill_cleanup();
 	dprintk(SONY_NC_DRIVER_NAME " removed.\n");
 
 	return 0;
#10 lore raw

PATCH RESEND v2 5/14 sony-laptop: new SNC setup and cleanup functions

In reply to Marco Chiappero

New SNC handles setup and cleanup functions, sony_nc_handles_setup and sony_nc_handles_cleanup. They avoid eccessive tainting of sony_nc_add and sony_nc_remove, with cleaner and easier to read code, better event initialization and better error handling. Due to name collision, the previously defined functions related to the handle list has been renamed sony_nc_handles_list_setup and sony_nc_handles_list_show.

---

drivers/platform/x86/sony-laptop.c +97 -19
@@ -810,14 +810,14 @@ error:
 	return length;
 }
 
-struct sony_nc_handles {
+struct sony_nc_handles_list {
 	u16 cap[0x10];
 	struct device_attribute devattr;
 };
 
-static struct sony_nc_handles *handles;
+static struct sony_nc_handles_list *handles;
 
-static ssize_t sony_nc_handles_show(struct device *dev,
+static ssize_t sony_nc_handles_list_show(struct device *dev,
 		struct device_attribute *attr, char *buffer)
 {
 	ssize_t len = 0;
@@ -832,7 +832,7 @@ static ssize_t sony_nc_handles_show(stru
 	return len;
 }
 
-static int sony_nc_handles_setup(struct platform_device *pd)
+static int sony_nc_handles_list_setup(struct platform_device *pd)
 {
 	unsigned int i, result;
 
@@ -853,7 +853,7 @@ static int sony_nc_handles_setup(struct 
 		sysfs_attr_init(&handles->devattr.attr);
 		handles->devattr.attr.name = "handles";
 		handles->devattr.attr.mode = S_IRUGO;
-		handles->devattr.show = sony_nc_handles_show;
+		handles->devattr.show = sony_nc_handles_list_show;
 
 		/* allow reading capabilities via sysfs */
 		if (device_create_file(&pd->dev, &handles->devattr)) {
@@ -866,7 +866,7 @@ static int sony_nc_handles_setup(struct 
 	return 0;
 }
 
-static int sony_nc_handles_cleanup(struct platform_device *pd)
+static int sony_nc_handles_list_cleanup(struct platform_device *pd)
 {
 	if (handles) {
 		if (debug)
@@ -1736,6 +1736,94 @@ static void sony_nc_backlight_cleanup(vo
 		backlight_device_unregister(sony_bl_props.dev);
 }
 
+static int sony_nc_handles_setup(struct platform_device *pd)
+{
+	unsigned int i, bitmask, result;
+	int ret;
+
+	/* retrieve the implemented offsets mask */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN00", 0x10, &bitmask))
+		return -EIO;
+
+	/* retrieve the available handles, otherwise return */
+	ret = sony_nc_handles_list_setup(pd);
+	if (ret)
+		return ret;
+
+	/* setup found handles here */
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+		int unsigned handle = handles->cap[i];
+
+		if (!handle)
+			continue;
+
+		dprintk("looking at handle 0x%.4x\n", handle);
+
+		switch (handle) {
+		case 0x0137:
+			ret = sony_nc_kbd_backlight_setup(pd);
+		case 0x0124:
+		case 0x0135:
+			ret = sony_nc_rfkill_setup(sony_nc_acpi_device);
+			break;
+		default:
+			continue;
+		}
+
+		if (ret < 0)
+			pr_warn("handle 0x%.4x setup failed (ret: %i)",
+								handle, ret);
+		else
+			dprintk("handle 0x%.4x setup completed\n", handle);
+	}
+
+	/* Enable all events for the found handles, otherwise return */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", bitmask, &result))
+		return -EIO;
+
+	return 0;
+}
+
+static int sony_nc_handles_cleanup(struct platform_device *pd)
+{
+	unsigned int i, result, bitmask;
+
+	/* retrieve the event enabled handles */
+	acpi_callgetfunc(sony_nc_acpi_handle, "SN01", &bitmask);
+
+	/* disable the event generation	for every handle */
+	acpi_callsetfunc(sony_nc_acpi_handle, "SN03", bitmask, &result);
+
+	/* cleanup handles here */
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+
+		int unsigned handle = handles->cap[i];
+
+		if (!handle)
+			continue;
+
+		dprintk("looking at handle 0x%.4x\n", handle);
+
+		switch (handle) {
+		case 0x0137:
+			sony_nc_kbd_backlight_cleanup(pd);
+		case 0x0124:
+		case 0x0135:
+			sony_nc_rfkill_cleanup();
+			break;
+		default:
+			continue;
+		}
+
+		dprintk("handle 0x%.4x deconfigured\n", handle);
+	}
+
+	/* finally cleanup the handles list */
+	sony_nc_handles_list_cleanup(pd);
+
+	return 0;
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
@@ -1783,21 +1871,17 @@ static int sony_nc_add(struct acpi_devic
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
 					 &handle))) {
 		dprintk("Doing SNC setup\n");
+		sony_nc_function_setup(device);
 		result = sony_nc_handles_setup(sony_pf_device);
 		if (result)
-			goto outpresent;
-		result = sony_nc_kbd_backlight_setup(sony_pf_device);
-		if (result)
 			goto outsnc;
-		sony_nc_function_setup(device);
-		sony_nc_rfkill_setup(device);
 	}
 
 	/* setup input devices and helper fifo */
 	result = sony_laptop_setup_input(device);
 	if (result) {
 		pr_err("Unable to create input devices\n");
-		goto outkbdbacklight;
+		goto outsnc;
 	}
 
 	if (acpi_video_backlight_support()) {
@@ -1855,9 +1939,6 @@ static int sony_nc_add(struct acpi_devic
 
 	sony_laptop_remove_input();
 
-      outkbdbacklight:
-	sony_nc_kbd_backlight_cleanup(sony_pf_device);
-
       outsnc:
 	sony_nc_handles_cleanup(sony_pf_device);
 
@@ -1865,7 +1946,6 @@ static int sony_nc_add(struct acpi_devic
 	sony_pf_remove();
 
       outwalk:
-	sony_nc_rfkill_cleanup();
 	return result;
 }
 
@@ -1874,6 +1954,7 @@ static int sony_nc_remove(struct acpi_de
 	struct sony_nc_value *item;
 
 	sony_nc_backlight_cleanup();
+	sony_nc_handles_cleanup(sony_pf_device);
 
 	sony_nc_acpi_device = NULL;
 
@@ -1881,11 +1962,8 @@ static int sony_nc_remove(struct acpi_de
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
 	}
 
-	sony_nc_kbd_backlight_cleanup(sony_pf_device);
-	sony_nc_handles_cleanup(sony_pf_device);
 	sony_pf_remove();
 	sony_laptop_remove_input();
-	sony_nc_rfkill_cleanup();
 	dprintk(SONY_NC_DRIVER_NAME " removed.\n");
 
 	return 0;
#11 lore raw

PATCH v2 6/14 sony-laptop: new sony_nc_handles_resume function

In reply to Marco Chiappero

New SNC resume function (sony_nc_handles_resume) for better event and handle re-initialization called by sony_nc_resume, now pushed downwards near sony_nc_add and sony_nc_cleanup for better readability and fewer function prototypes.

---

drivers/platform/x86/sony-laptop.c +73 -39
@@ -1241,45 +1241,6 @@ static int sony_nc_function_setup(struct
 	return 0;
 }
 
-static int sony_nc_resume(struct acpi_device *device)
-{
-	struct sony_nc_value *item;
-	acpi_handle handle;
-
-	for (item = sony_nc_values; item->name; item++) {
-		int ret;
-
-		if (!item->valid)
-			continue;
-		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
-				       item->value, NULL);
-		if (ret < 0) {
-			pr_err("%s: %d\n", __func__, ret);
-			break;
-		}
-	}
-
-	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
-					 &handle))) {
-		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
-			dprintk("ECON Method failed\n");
-	}
-
-	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
-					 &handle))) {
-		dprintk("Doing SNC setup\n");
-		sony_nc_function_setup(device);
-	}
-
-	/* re-read rfkill state */
-	sony_nc_rfkill_update();
-
-	/* restore kbd backlight states */
-	sony_nc_kbd_backlight_resume();
-
-	return 0;
-}
-
 static void sony_nc_rfkill_cleanup(void)
 {
 	int i;
@@ -1824,6 +1785,45 @@ static int sony_nc_handles_cleanup(struc
 	return 0;
 }
 
+static int sony_nc_handles_resume(void)
+{
+	unsigned int i, result, bitmask;
+
+	/* retrieve the implemented offsets mask */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN00", 0x10, &bitmask))
+		return -EIO;
+
+	/* Enable all events, otherwise return */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", bitmask, &result))
+		return -EIO;
+
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+		int unsigned handle = handles->cap[i];
+
+		if (!handle)
+			continue;
+
+		dprintk("looking at handle 0x%.4x\n", handle);
+
+		switch (handle) {
+		case 0x0137: /* kbd + als */
+			sony_nc_kbd_backlight_resume();
+			break;
+		case 0x0124:
+		case 0x0135:
+			/* re-read rfkill state */
+			sony_nc_rfkill_update();
+			break;
+		default:
+			continue;
+		}
+
+		dprintk("handle 0x%.4x updated\n", handle);
+	}
+
+	return 0;
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
@@ -1969,6 +1969,40 @@ static int sony_nc_remove(struct acpi_de
 	return 0;
 }
 
+static int sony_nc_resume(struct acpi_device *device)
+{
+	struct sony_nc_value *item;
+	acpi_handle handle;
+
+	for (item = sony_nc_values; item->name; item++) {
+		int ret;
+
+		if (!item->valid)
+			continue;
+		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
+				       item->value, NULL);
+		if (ret < 0) {
+			pr_err("%s: %d\n", __func__, ret);
+			break;
+		}
+	}
+
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
+					 &handle))) {
+		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
+			dprintk("ECON Method failed\n");
+	}
+
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
+					 &handle))) {
+		dprintk("Doing SNC setup\n");
+		sony_nc_function_setup(device);
+		sony_nc_handles_resume();
+	}
+
+	return 0;
+}
+
 static const struct acpi_device_id sony_device_ids[] = {
 	{SONY_NC_HID, 0},
 	{SONY_PIC_HID, 0},
#12 lore raw

PATCH RESEND v2 6/14 sony-laptop: new sony_nc_handles_resume function

In reply to Marco Chiappero

New SNC resume function (sony_nc_handles_resume) for better event and handle re-initialization called by sony_nc_resume, now pushed downwards near sony_nc_add and sony_nc_cleanup for better readability and fewer function prototypes.

---

drivers/platform/x86/sony-laptop.c +73 -39
@@ -1241,45 +1241,6 @@ static int sony_nc_function_setup(struct
 	return 0;
 }
 
-static int sony_nc_resume(struct acpi_device *device)
-{
-	struct sony_nc_value *item;
-	acpi_handle handle;
-
-	for (item = sony_nc_values; item->name; item++) {
-		int ret;
-
-		if (!item->valid)
-			continue;
-		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
-				       item->value, NULL);
-		if (ret < 0) {
-			pr_err("%s: %d\n", __func__, ret);
-			break;
-		}
-	}
-
-	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
-					 &handle))) {
-		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
-			dprintk("ECON Method failed\n");
-	}
-
-	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
-					 &handle))) {
-		dprintk("Doing SNC setup\n");
-		sony_nc_function_setup(device);
-	}
-
-	/* re-read rfkill state */
-	sony_nc_rfkill_update();
-
-	/* restore kbd backlight states */
-	sony_nc_kbd_backlight_resume();
-
-	return 0;
-}
-
 static void sony_nc_rfkill_cleanup(void)
 {
 	int i;
@@ -1824,6 +1785,45 @@ static int sony_nc_handles_cleanup(struc
 	return 0;
 }
 
+static int sony_nc_handles_resume(void)
+{
+	unsigned int i, result, bitmask;
+
+	/* retrieve the implemented offsets mask */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN00", 0x10, &bitmask))
+		return -EIO;
+
+	/* Enable all events, otherwise return */
+	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", bitmask, &result))
+		return -EIO;
+
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+		int unsigned handle = handles->cap[i];
+
+		if (!handle)
+			continue;
+
+		dprintk("looking at handle 0x%.4x\n", handle);
+
+		switch (handle) {
+		case 0x0137: /* kbd + als */
+			sony_nc_kbd_backlight_resume();
+			break;
+		case 0x0124:
+		case 0x0135:
+			/* re-read rfkill state */
+			sony_nc_rfkill_update();
+			break;
+		default:
+			continue;
+		}
+
+		dprintk("handle 0x%.4x updated\n", handle);
+	}
+
+	return 0;
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
@@ -1969,6 +1969,40 @@ static int sony_nc_remove(struct acpi_de
 	return 0;
 }
 
+static int sony_nc_resume(struct acpi_device *device)
+{
+	struct sony_nc_value *item;
+	acpi_handle handle;
+
+	for (item = sony_nc_values; item->name; item++) {
+		int ret;
+
+		if (!item->valid)
+			continue;
+		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
+				       item->value, NULL);
+		if (ret < 0) {
+			pr_err("%s: %d\n", __func__, ret);
+			break;
+		}
+	}
+
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
+					 &handle))) {
+		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
+			dprintk("ECON Method failed\n");
+	}
+
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
+					 &handle))) {
+		dprintk("Doing SNC setup\n");
+		sony_nc_function_setup(device);
+		sony_nc_handles_resume();
+	}
+
+	return 0;
+}
+
 static const struct acpi_device_id sony_device_ids[] = {
 	{SONY_NC_HID, 0},
 	{SONY_PIC_HID, 0},
#13 lore raw

PATCH v2 7/14 sony-laptop: sony_nc_function_setup modifications

In reply to Marco Chiappero

Removed every init code, already present in sony_nc_snc_setup and sony_nc_snc_resume. Now calling only the handles present on the device, using the new setup and resume code.

---

drivers/platform/x86/sony-laptop.c +19 -11
@@ -1225,18 +1225,14 @@ static acpi_status sony_walk_callback(ac
 /*
  * ACPI device
  */
-static int sony_nc_function_setup(struct acpi_device *device)
+static int sony_nc_function_setup(unsigned int handle)
 {
 	unsigned int result;
 
-	/* Enable all events */
-	acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
-
-	/* Setup hotkeys */
-	sony_call_snc_handle(0x0100, 0, &result);
-	sony_call_snc_handle(0x0101, 0, &result);
-	sony_call_snc_handle(0x0102, 0x100, &result);
-	sony_call_snc_handle(0x0127, 0, &result);
+	if (handle == 0x0102)
+		sony_call_snc_handle(0x0102, 0x100, &result);
+	else
+		sony_call_snc_handle(handle, 0, &result);
 
 	return 0;
 }
@@ -1721,6 +1717,12 @@ static int sony_nc_handles_setup(struct 
 		dprintk("looking at handle 0x%.4x\n", handle);
 
 		switch (handle) {
+		case 0x0100:
+		case 0x0127:
+		case 0x0101:
+		case 0x0102:
+			ret = sony_nc_function_setup(handle);
+			break;
 		case 0x0137:
 			ret = sony_nc_kbd_backlight_setup(pd);
 		case 0x0124:
@@ -1806,6 +1808,12 @@ static int sony_nc_handles_resume(void)
 		dprintk("looking at handle 0x%.4x\n", handle);
 
 		switch (handle) {
+		case 0x0100:
+		case 0x0127:
+		case 0x0101:
+		case 0x0102:
+			sony_nc_function_setup(handle);
+			break;
 		case 0x0137: /* kbd + als */
 			sony_nc_kbd_backlight_resume();
 			break;
@@ -1871,7 +1879,7 @@ static int sony_nc_add(struct acpi_devic
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
 					 &handle))) {
 		dprintk("Doing SNC setup\n");
-		sony_nc_function_setup(device);
+
 		result = sony_nc_handles_setup(sony_pf_device);
 		if (result)
 			goto outsnc;
@@ -1996,7 +2004,7 @@ static int sony_nc_resume(struct acpi_de
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
 					 &handle))) {
 		dprintk("Doing SNC setup\n");
-		sony_nc_function_setup(device);
+
 		sony_nc_handles_resume();
 	}
 
#14 lore raw

PATCH RESEND v2 7/14 sony-laptop: sony_nc_function_setup modifications

In reply to Marco Chiappero

Removed every init code, already present in sony_nc_snc_setup and sony_nc_snc_resume. Now calling only the handles present on the device, using the new setup and resume code.

---

drivers/platform/x86/sony-laptop.c +19 -11
@@ -1225,18 +1225,14 @@ static acpi_status sony_walk_callback(ac
 /*
  * ACPI device
  */
-static int sony_nc_function_setup(struct acpi_device *device)
+static int sony_nc_function_setup(unsigned int handle)
 {
 	unsigned int result;
 
-	/* Enable all events */
-	acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
-
-	/* Setup hotkeys */
-	sony_call_snc_handle(0x0100, 0, &result);
-	sony_call_snc_handle(0x0101, 0, &result);
-	sony_call_snc_handle(0x0102, 0x100, &result);
-	sony_call_snc_handle(0x0127, 0, &result);
+	if (handle == 0x0102)
+		sony_call_snc_handle(0x0102, 0x100, &result);
+	else
+		sony_call_snc_handle(handle, 0, &result);
 
 	return 0;
 }
@@ -1721,6 +1717,12 @@ static int sony_nc_handles_setup(struct 
 		dprintk("looking at handle 0x%.4x\n", handle);
 
 		switch (handle) {
+		case 0x0100:
+		case 0x0127:
+		case 0x0101:
+		case 0x0102:
+			ret = sony_nc_function_setup(handle);
+			break;
 		case 0x0137:
 			ret = sony_nc_kbd_backlight_setup(pd);
 		case 0x0124:
@@ -1806,6 +1808,12 @@ static int sony_nc_handles_resume(void)
 		dprintk("looking at handle 0x%.4x\n", handle);
 
 		switch (handle) {
+		case 0x0100:
+		case 0x0127:
+		case 0x0101:
+		case 0x0102:
+			sony_nc_function_setup(handle);
+			break;
 		case 0x0137: /* kbd + als */
 			sony_nc_kbd_backlight_resume();
 			break;
@@ -1871,7 +1879,7 @@ static int sony_nc_add(struct acpi_devic
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
 					 &handle))) {
 		dprintk("Doing SNC setup\n");
-		sony_nc_function_setup(device);
+
 		result = sony_nc_handles_setup(sony_pf_device);
 		if (result)
 			goto outsnc;
@@ -1996,7 +2004,7 @@ static int sony_nc_resume(struct acpi_de
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
 					 &handle))) {
 		dprintk("Doing SNC setup\n");
-		sony_nc_function_setup(device);
+
 		sony_nc_handles_resume();
 	}
 
maintainer
#15 lore raw
In reply to Marco Chiappero
Quoted 12 lines · Marco Chiappero

Hello,

here is the first part of the V2 patches sent by me on the 3rd of June. As I have no spare time for coding at the moment, I have to split the previous patchset into two parts, I need more time for some patches while I have the first ones ready laying around. So these patches I'm sending include improvements to the current code and minor support extension, but no new features, that will come later in the second part. Note that patch numbers no longer match with the previous patchset that should be discarded, as is being totally replaced by this set and by the next one, available hopefully soon.

Quoted 2 lines

These patches are also available at
http://www.absence.it/vaio-acpi/source/patches/patchset-v2/

a number of patches got line wrapped by your MUA, would you mind re-sending them fixing it?

Signature · 2 lines
mattia
:wq!
#16 lore raw

Il 10/09/2011 06:03, Mattia Dongili ha scritto:

Quoted 3 lines

a number of patches got line wrapped by your MUA, would you mind re-sending them fixing it?

I'm sorry, I though it was already set up correctly, wrong assumption...
To avoid confusion, I've sent again every single patch even though not necessary. I hope everything to be fine now.

#17 lore raw

PATCH v2 8/14 sony-laptop: sony_nc_notify rewritten and improved

In reply to Marco Chiappero

sony_nc_notify rewritten (and placed near the other acpi callbacks), the hotkey decoding code moved to a new function sony_nc_hotkeys_decode.

---

drivers/platform/x86/sony-laptop.c +94 -56
@@ -1151,62 +1151,6 @@ static struct sony_nc_event sony_127_eve
 /*
  * ACPI callbacks
  */
-static void sony_nc_notify(struct acpi_device *device, u32 event)
-{
-	u32 ev = event;
-
-	if (ev >= 0x90) {
-		/* New-style event */
-		unsigned int result;
-		int key_handle = 0;
-		ev -= 0x90;
-
-		if (sony_find_snc_handle(0x100) == ev)
-			key_handle = 0x100;
-		if (sony_find_snc_handle(0x127) == ev)
-			key_handle = 0x127;
-
-		if (key_handle) {
-			struct sony_nc_event *key_event;
-
-			if (sony_call_snc_handle(key_handle, 0x200, &result)) {
-				dprintk("sony_nc_notify, unable to decode"
-					" event 0x%.2x 0x%.2x\n", key_handle,
-					ev);
-				/* restore the original event */
-				ev = event;
-			} else {
-				ev = result & 0xFF;
-
-				if (key_handle == 0x100)
-					key_event = sony_100_events;
-				else
-					key_event = sony_127_events;
-
-				for (; key_event->data; key_event++) {
-					if (key_event->data == ev) {
-						ev = key_event->event;
-						break;
-					}
-				}
-
-				if (!key_event->data)
-					pr_info("Unknown event: 0x%x 0x%x\n",
-						key_handle, ev);
-				else
-					sony_laptop_report_input_event(ev);
-			}
-		} else if (sony_find_snc_handle(sony_rfkill_handle) == ev) {
-			sony_nc_rfkill_update();
-			return;
-		}
-	} else
-		sony_laptop_report_input_event(ev);
-
-	dprintk("sony_nc_notify, event: 0x%.2x\n", ev);
-	acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
-}
-
 static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
 				      void *context, void **return_value)
 {
@@ -1237,6 +1181,41 @@ static int sony_nc_function_setup(unsign
 	return 0;
 }
 
+static int sony_nc_hotkeys_decode(unsigned int handle)
+{
+	int ret = -EINVAL;
+	unsigned int result = 0;
+	struct sony_nc_event *key_event;
+
+	if (sony_call_snc_handle(handle, 0x200, &result)) {
+		dprintk("sony_nc_hotkeys_decode,"
+				" unable to retrieve the hotkey\n");
+	} else {
+		result &= 0xff;
+
+		if (handle == 0x100)
+			key_event = sony_100_events;
+		else
+			key_event = sony_127_events;
+
+		for (; key_event->data; key_event++) {
+			if (key_event->data == result) {
+				ret = key_event->event;
+				break;
+			}
+		}
+
+		if (!key_event->data)
+			pr_info("Unknown hotkey 0x%.2x (handle 0x%.2x)\n",
+							result, handle);
+		else
+			dprintk("sony_nc_hotkeys_decode, hotkey 0x%.2x decoded "
+					"to event 0x%.2x\n", result, ret);
+	}
+
+	return ret;
+}
+
 static void sony_nc_rfkill_cleanup(void)
 {
 	int i;
@@ -1832,6 +1811,65 @@ static int sony_nc_handles_resume(void)
 	return 0;
 }
 
+static void sony_nc_notify(struct acpi_device *device, u32 event)
+{
+	dprintk("sony_nc_notify, event: 0x%.2x\n", event);
+
+	/* handles related events */
+	if (event >= 0x90) {
+		unsigned int result = 0, handle = 0, value = 0;
+
+		/* the event should corrispond to the offset of the method */
+		unsigned int offset = event - 0x90;
+
+		handle = handles->cap[offset];
+		switch (handle) {
+		/* list of handles known for generating events */
+		case 0x0100:
+		case 0x0127:
+			/* hotkey event, a key has been pressed, retrieve it */
+			value = sony_nc_hotkeys_decode(handle);
+			if (value > 0) { /* known event */
+				sony_laptop_report_input_event(value);
+			} else {
+				/* restore the original event for
+				   the acpi bus notification */
+				value = event;
+			}
+
+			acpi_bus_generate_proc_event(sony_nc_acpi_device, 1,
+									value);
+
+			break;
+
+		case 0x0124:
+		case 0x0135:
+			sony_call_snc_handle(handle, 0x0100, &result);
+			result &= 0x03;
+			dprintk("sony_nc_notify, RFKILL event received "
+					"(reason: %s)\n", result == 1 ?
+					"switch state changed" : "battery");
+
+			if (result == 1) { /* hw swtich event */
+				sony_nc_rfkill_update();
+			}
+
+			break;
+
+		default:
+			dprintk("Unknowk event for handle: 0x%x\n", handle);
+			break;
+		}
+
+		/* clear the event (and the event reason when present) */
+		acpi_callsetfunc(sony_nc_acpi_handle, "SN05", 1 << offset,
+				&result);
+	} else {
+		sony_laptop_report_input_event(event);
+		acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, event);
+	}
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
#18 lore raw

PATCH RESEND v2 8/14 sony-laptop: sony_nc_notify rewritten and improved

In reply to Marco Chiappero

sony_nc_notify rewritten (and placed near the other acpi callbacks), the hotkey decoding code moved to a new function sony_nc_hotkeys_decode.

---

drivers/platform/x86/sony-laptop.c +94 -56
@@ -1151,62 +1151,6 @@ static struct sony_nc_event sony_127_eve
 /*
  * ACPI callbacks
  */
-static void sony_nc_notify(struct acpi_device *device, u32 event)
-{
-	u32 ev = event;
-
-	if (ev >= 0x90) {
-		/* New-style event */
-		unsigned int result;
-		int key_handle = 0;
-		ev -= 0x90;
-
-		if (sony_find_snc_handle(0x100) == ev)
-			key_handle = 0x100;
-		if (sony_find_snc_handle(0x127) == ev)
-			key_handle = 0x127;
-
-		if (key_handle) {
-			struct sony_nc_event *key_event;
-
-			if (sony_call_snc_handle(key_handle, 0x200, &result)) {
-				dprintk("sony_nc_notify, unable to decode"
-					" event 0x%.2x 0x%.2x\n", key_handle,
-					ev);
-				/* restore the original event */
-				ev = event;
-			} else {
-				ev = result & 0xFF;
-
-				if (key_handle == 0x100)
-					key_event = sony_100_events;
-				else
-					key_event = sony_127_events;
-
-				for (; key_event->data; key_event++) {
-					if (key_event->data == ev) {
-						ev = key_event->event;
-						break;
-					}
-				}
-
-				if (!key_event->data)
-					pr_info("Unknown event: 0x%x 0x%x\n",
-						key_handle, ev);
-				else
-					sony_laptop_report_input_event(ev);
-			}
-		} else if (sony_find_snc_handle(sony_rfkill_handle) == ev) {
-			sony_nc_rfkill_update();
-			return;
-		}
-	} else
-		sony_laptop_report_input_event(ev);
-
-	dprintk("sony_nc_notify, event: 0x%.2x\n", ev);
-	acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
-}
-
 static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
 				      void *context, void **return_value)
 {
@@ -1237,6 +1181,41 @@ static int sony_nc_function_setup(unsign
 	return 0;
 }
 
+static int sony_nc_hotkeys_decode(unsigned int handle)
+{
+	int ret = -EINVAL;
+	unsigned int result = 0;
+	struct sony_nc_event *key_event;
+
+	if (sony_call_snc_handle(handle, 0x200, &result)) {
+		dprintk("sony_nc_hotkeys_decode,"
+				" unable to retrieve the hotkey\n");
+	} else {
+		result &= 0xff;
+
+		if (handle == 0x100)
+			key_event = sony_100_events;
+		else
+			key_event = sony_127_events;
+
+		for (; key_event->data; key_event++) {
+			if (key_event->data == result) {
+				ret = key_event->event;
+				break;
+			}
+		}
+
+		if (!key_event->data)
+			pr_info("Unknown hotkey 0x%.2x (handle 0x%.2x)\n",
+							result, handle);
+		else
+			dprintk("sony_nc_hotkeys_decode, hotkey 0x%.2x decoded "
+					"to event 0x%.2x\n", result, ret);
+	}
+
+	return ret;
+}
+
 static void sony_nc_rfkill_cleanup(void)
 {
 	int i;
@@ -1832,6 +1811,65 @@ static int sony_nc_handles_resume(void)
 	return 0;
 }
 
+static void sony_nc_notify(struct acpi_device *device, u32 event)
+{
+	dprintk("sony_nc_notify, event: 0x%.2x\n", event);
+
+	/* handles related events */
+	if (event >= 0x90) {
+		unsigned int result = 0, handle = 0, value = 0;
+
+		/* the event should corrispond to the offset of the method */
+		unsigned int offset = event - 0x90;
+
+		handle = handles->cap[offset];
+		switch (handle) {
+		/* list of handles known for generating events */
+		case 0x0100:
+		case 0x0127:
+			/* hotkey event, a key has been pressed, retrieve it */
+			value = sony_nc_hotkeys_decode(handle);
+			if (value > 0) { /* known event */
+				sony_laptop_report_input_event(value);
+			} else {
+				/* restore the original event for
+				   the acpi bus notification */
+				value = event;
+			}
+
+			acpi_bus_generate_proc_event(sony_nc_acpi_device, 1,
+									value);
+
+			break;
+
+		case 0x0124:
+		case 0x0135:
+			sony_call_snc_handle(handle, 0x0100, &result);
+			result &= 0x03;
+			dprintk("sony_nc_notify, RFKILL event received "
+					"(reason: %s)\n", result == 1 ?
+					"switch state changed" : "battery");
+
+			if (result == 1) { /* hw swtich event */
+				sony_nc_rfkill_update();
+			}
+
+			break;
+
+		default:
+			dprintk("Unknowk event for handle: 0x%x\n", handle);
+			break;
+		}
+
+		/* clear the event (and the event reason when present) */
+		acpi_callsetfunc(sony_nc_acpi_handle, "SN05", 1 << offset,
+				&result);
+	} else {
+		sony_laptop_report_input_event(event);
+		acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, event);
+	}
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
#19 lore raw

PATCH v2 9/14 sony-laptop: sony_walk_callback moved for better readability

In reply to Marco Chiappero

sony_walk_callback moved to stay close to the other ACPI callbacks for better code readability.

---

drivers/platform/x86/sony-laptop.c +18 -18
@@ -1149,24 +1149,6 @@ static struct sony_nc_event sony_127_eve
 };
 
 /*
- * ACPI callbacks
- */
-static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
-				      void *context, void **return_value)
-{
-	struct acpi_device_info *info;
-
-	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-		pr_warn("method: name: %4.4s, args %X\n",
-			(char *)&info->name, info->param_count);
-
-		kfree(info);
-	}
-
-	return AE_OK;
-}
-
-/*
  * ACPI device
  */
 static int sony_nc_function_setup(unsigned int handle)
@@ -1811,6 +1793,24 @@ static int sony_nc_handles_resume(void)
 	return 0;
 }
 
+/*
+ * ACPI callbacks
+ */
+static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
+				      void *context, void **return_value)
+{
+	struct acpi_device_info *info;
+
+	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
+		pr_warn("method: name: %4.4s, args %X\n",
+			(char *)&info->name, info->param_count);
+
+		kfree(info);
+	}
+
+	return AE_OK;
+}
+
 static void sony_nc_notify(struct acpi_device *device, u32 event)
 {
 	dprintk("sony_nc_notify, event: 0x%.2x\n", event);
#20 lore raw

PATCH RESEND v2 9/14 sony-laptop: sony_walk_callback moved for better readability

In reply to Marco Chiappero

sony_walk_callback moved to stay close to the other ACPI callbacks for better code readability.

---

drivers/platform/x86/sony-laptop.c +18 -18
@@ -1149,24 +1149,6 @@ static struct sony_nc_event sony_127_eve
 };
 
 /*
- * ACPI callbacks
- */
-static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
-				      void *context, void **return_value)
-{
-	struct acpi_device_info *info;
-
-	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-		pr_warn("method: name: %4.4s, args %X\n",
-			(char *)&info->name, info->param_count);
-
-		kfree(info);
-	}
-
-	return AE_OK;
-}
-
-/*
  * ACPI device
  */
 static int sony_nc_function_setup(unsigned int handle)
@@ -1811,6 +1793,24 @@ static int sony_nc_handles_resume(void)
 	return 0;
 }
 
+/*
+ * ACPI callbacks
+ */
+static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
+				      void *context, void **return_value)
+{
+	struct acpi_device_info *info;
+
+	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
+		pr_warn("method: name: %4.4s, args %X\n",
+			(char *)&info->name, info->param_count);
+
+		kfree(info);
+	}
+
+	return AE_OK;
+}
+
 static void sony_nc_notify(struct acpi_device *device, u32 event)
 {
 	dprintk("sony_nc_notify, event: 0x%.2x\n", event);
#21 lore raw

PATCH v2 10/14 sony-laptop: code style fixes

In reply to Marco Chiappero

This patch fixes all ERROR and WARNING complains by checkpatch.

---

drivers/platform/x86/sony-laptop.c +1 -2
@@ -63,7 +63,7 @@
 #include <linux/slab.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/sonypi.h>
 #include <linux/sony-laptop.h>
 #include <linux/rfkill.h>
@@ -377,11 +377,13 @@ static void sony_laptop_report_input_eve
 
 	default:
 		if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
-			dprintk("sony_laptop_report_input_event, event not known: %d\n",

event);
+ dprintk("sony_laptop_report_input_event, "
+ "event not known: %d\n", event);
break;
}
if (sony_laptop_input_index[event] != -1) {
- kp.key =
sony_laptop_input_keycode_map[sony_laptop_input_index[event]];
+ int index = sony_laptop_input_index[event];
+ kp.key = sony_laptop_input_keycode_map[index];
if (kp.key != KEY_UNKNOWN)
kp.dev = key_dev;
}
@@ -565,12 +567,12 @@ static int sony_pf_add(void)

return 0;

- out_platform_alloced:
+out_platform_alloced:
platform_device_put(sony_pf_device); sony_pf_device = NULL;
- out_platform_registered:
+out_platform_registered:
platform_driver_unregister(&sony_pf_driver);
- out:
+out:
atomic_dec(&sony_pf_users);
return ret;
}
@@ -622,7 +624,8 @@ struct sony_nc_value {
.acpiset = _setters, \
.validate = _validate, \
.debug = _debug, \
- .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store),
\
+ .devattr = __ATTR(_name, 0, sony_nc_sysfs_show, \
+ sony_nc_sysfs_store), \
}

#define SNC_HANDLE_NULL { .name = NULL }
@@ -664,7 +667,8 @@ static struct sony_nc_value sony_nc_valu
SNC_HANDLE(brightness_default, snc_brightness_def_get,
snc_brightness_def_set, brightness_default_validate, 0),
SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
- SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set,
boolean_validate, 0),
+ SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set,
+ boolean_validate, 0),
SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
boolean_validate, 0),
SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
@@ -684,7 +688,7 @@ static struct sony_nc_value sony_nc_valu
};

static acpi_handle sony_nc_acpi_handle;
-static struct acpi_device *sony_nc_acpi_device = NULL; +static struct acpi_device *sony_nc_acpi_device;

/*
* acpi_evaluate_object wrappers
@@ -731,7 +735,8 @@ static int acpi_callsetfunc(acpi_handle
if (status == AE_OK) {
if (result != NULL) {
if (out_obj.type != ACPI_TYPE_INTEGER) {
- pr_warn("acpi_evaluate_object bad return type\n");
+ pr_warn("acpi_evaluate_object bad "
+ "return type\n");
return -1;
}
*result = out_obj.integer.value;
@@ -944,11 +949,11 @@ static int sony_call_snc_handle_buffer(u
static int brightness_default_validate(const int direction, const int
value)
{
switch (direction) {
- case SNC_VALIDATE_OUT:
- return value - 1;
- case SNC_VALIDATE_IN:
- if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
- return value + 1;
+ case SNC_VALIDATE_OUT:
+ return value - 1;
+ case SNC_VALIDATE_IN:
+ if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
+ return value + 1;
}
return -EINVAL;
}
@@ -970,8 +975,9 @@ static int boolean_validate(const int di
/*
* Sysfs show/store common to all sony_nc_values
*/
-static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
- char *buffer)
+static ssize_t sony_nc_sysfs_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buffer)
{
unsigned int value;
struct sony_nc_value *item =
@@ -1012,7 +1018,8 @@ static ssize_t sony_nc_sysfs_store(struc
if (value < 0)
return value;

- if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL)
< 0)
+ if (acpi_callsetfunc(sony_nc_acpi_handle,
+ *item->acpiset, value, NULL) < 0)
return -EIO;
item->value = value;
item->valid = 1;
@@ -1290,9 +1297,9 @@ static void sony_nc_rfkill_update(void)
continue;

if (hwblock) {
- if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
- /* we already know we're blocked */
- }
+ if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
+ /* we already know we're blocked */ ;
+
continue;
}

@@ -1886,7 +1893,8 @@ static int sony_nc_add(struct acpi_devic

/* read device status */
result = acpi_bus_get_status(device);
- /* bail IFF the above call was successful and the device is not
present */
+ /* bail IFF the above call was successful
+ and the device is not present */
if (!result && !device->status.present) {
dprintk("Device not present\n"); result = -ENODEV;
@@ -1930,11 +1938,11 @@ static int sony_nc_add(struct acpi_devic
goto outsnc;
}

- if (acpi_video_backlight_support()) {
- pr_info("brightness ignored, must be controlled by ACPI video driver
\n");
- } else {
+ if (acpi_video_backlight_support())
+ pr_info("brightness ignored, must be "
+ "controlled by ACPI video driver\n");
+ else
sony_nc_backlight_setup();
- }

/* create sony_pf sysfs attributes related to the SNC device */ for (item = sony_nc_values; item->name; ++item) {
@@ -1977,21 +1985,21 @@ static int sony_nc_add(struct acpi_devic

return 0;

- out_sysfs:
- for (item = sony_nc_values; item->name; ++item) {
+out_sysfs:
+ for (item = sony_nc_values; item->name; ++item)
device_remove_file(&sony_pf_device->dev, &item->devattr);
- }
+
sony_nc_backlight_cleanup();

sony_laptop_remove_input();

- outsnc:
+outsnc:
sony_nc_handles_cleanup(sony_pf_device);

- outpresent:
+outpresent:
sony_pf_remove();

- outwalk:
+outwalk:
return result;
}

@@ -2004,9 +2012,8 @@ static int sony_nc_remove(struct acpi_de

sony_nc_acpi_device = NULL;

- for (item = sony_nc_values; item->name; ++item) {
+ for (item = sony_nc_values; item->name; ++item)
device_remove_file(&sony_pf_device->dev, &item->devattr);
- }

sony_pf_remove();
sony_laptop_remove_input();
@@ -2387,11 +2394,14 @@ static u8 sony_pic_call3(u8 dev, u8 fn,
{
u8 v1;

- wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
ITERATIONS_LONG);
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
+ ITERATIONS_LONG);
outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
- wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
ITERATIONS_LONG);
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
+ ITERATIONS_LONG);
outb(fn, spic_dev.cur_ioport->io1.minimum);
- wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
ITERATIONS_LONG);
+ wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
+ ITERATIONS_LONG);
outb(v, spic_dev.cur_ioport->io1.minimum);
v1 = inb_p(spic_dev.cur_ioport->io1.minimum); dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
@@ -2505,19 +2515,19 @@ out:
/* the rest don't need a loop until not 0xff */
#define SONYPI_CAMERA_AGC 6
#define SONYPI_CAMERA_AGC_MASK 0x30
-#define SONYPI_CAMERA_SHUTTER_MASK 0x7
+#define SONYPI_CAMERA_SHUTTER_MASK 0x7

#define SONYPI_CAMERA_SHUTDOWN_REQUEST 7
#define SONYPI_CAMERA_CONTROL 0x10

-#define SONYPI_CAMERA_STATUS 7
-#define SONYPI_CAMERA_STATUS_READY 0x2
+#define SONYPI_CAMERA_STATUS 7
+#define SONYPI_CAMERA_STATUS_READY 0x2
#define SONYPI_CAMERA_STATUS_POSITION 0x4

-#define SONYPI_DIRECTION_BACKWARDS 0x4
+#define SONYPI_DIRECTION_BACKWARDS 0x4

-#define SONYPI_CAMERA_REVISION 8
-#define SONYPI_CAMERA_ROMVERSION 9
+#define SONYPI_CAMERA_REVISION 8
+#define SONYPI_CAMERA_ROMVERSION 9

static int __sony_pic_camera_ready(void)
{
@@ -2559,14 +2569,14 @@ static int __sony_pic_camera_on(void)

for (j = 5; j > 0; j--) {

- for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
- msleep(10);
+ for (x = 0; x < 50 && sony_pic_call2(0x91, 0x1); x++)
+ msleep(20);
sony_pic_call1(0x93);

- for (i = 400; i > 0; i--) {
+ for (i = 200; i > 0; i--) {
if (__sony_pic_camera_ready())
break;
- msleep(10);
+ msleep(20);
}
if (i)
break;
@@ -2601,28 +2611,28 @@ int sony_pic_camera_command(int command,
__sony_pic_camera_off();
break;
case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
- wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS,
value),
- ITERATIONS_SHORT);
+ wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS,
+ value), ITERATIONS_SHORT);
break;
case SONY_PIC_COMMAND_SETCAMERACONTRAST:
- wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
- ITERATIONS_SHORT);
+ wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST,
+ value), ITERATIONS_SHORT);
break;
case SONY_PIC_COMMAND_SETCAMERAHUE:
wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
ITERATIONS_SHORT);
break;
case SONY_PIC_COMMAND_SETCAMERACOLOR:
- wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
- ITERATIONS_SHORT);
+ wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR,
+ value), ITERATIONS_SHORT);
break;
case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
- wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
- ITERATIONS_SHORT);
+ wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS,
+ value), ITERATIONS_SHORT);
break;
case SONY_PIC_COMMAND_SETCAMERAPICTURE:
- wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
- ITERATIONS_SHORT);
+ wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
+ value), ITERATIONS_SHORT);
break;
case SONY_PIC_COMMAND_SETCAMERAAGC:
wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
@@ -3089,7 +3099,8 @@ sony_pic_read_possible_resource(struct a
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
{
/* start IO enumeration */
- struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport),
GFP_KERNEL);
+ struct sony_pic_ioport *ioport =
+ kzalloc(sizeof(*ioport), GFP_KERNEL);
if (!ioport)
return AE_ERROR;

@@ -3137,7 +3148,8 @@ sony_pic_read_possible_resource(struct a
{
struct acpi_resource_io *io = &resource->data.io; struct sony_pic_ioport *ioport =
- list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
+ list_first_entry(&dev->ioports,
+ struct sony_pic_ioport, list);
if (!io) {
dprintk("Blank IO resource\n"); return AE_OK;
@@ -3145,16 +3157,17 @@ sony_pic_read_possible_resource(struct a

if (!ioport->io1.minimum) {
memcpy(&ioport->io1, io, sizeof(*io));
- dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
+ dprintk("IO1 at 0x%.4x (0x%.2x)\n",
+ ioport->io1.minimum,
ioport->io1.address_length);
- }
- else if (!ioport->io2.minimum) {
+ } else if (!ioport->io2.minimum) {
memcpy(&ioport->io2, io, sizeof(*io));
- dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
+ dprintk("IO2 at 0x%.4x (0x%.2x)\n",
+ ioport->io2.minimum,
ioport->io2.address_length);
- }
- else {
- pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
+ } else {
+ pr_err("Unknown SPIC Type, "
+ "more than 2 IO Ports\n");
return AE_ERROR;
}
return AE_OK;
@@ -3477,24 +3490,26 @@ static int sony_pic_add(struct acpi_devi
/* Type 1 have 2 ioports */
if (io->io2.minimum) {
if (request_region(io->io2.minimum,
- io->io2.address_length,
- "Sony Programmable I/O Device")) {
- dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
- io->io2.minimum, io->io2.maximum,
+ io->io2.address_length,
+ "Sony Programmable I/O Device")) {
+ dprintk("I/O port2: 0x%.4x (0x%.4x) "
+ "+ 0x%.2x\n",
+ io->io2.minimum,
+ io->io2.maximum,
io->io2.address_length);
spic_dev.cur_ioport = io; break;
- }
- else {
+ } else {
dprintk("Unable to get I/O port2: "
- "0x%.4x (0x%.4x) + 0x%.2x\n",
- io->io2.minimum, io->io2.maximum,
+ "0x%.4x (0x%.4x) "
+ "+ 0x%.2x\n",
+ io->io2.minimum,
+ io->io2.maximum,
io->io2.address_length);
release_region(io->io1.minimum,
io->io1.address_length);
}
- }
- else {
+ } else {
spic_dev.cur_ioport = io;
break;
}
@@ -3509,7 +3524,7 @@ static int sony_pic_add(struct acpi_devi
/* request IRQ */
list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
- IRQF_DISABLED, "sony-laptop", &spic_dev)) {
+ IRQF_DISABLED, "sony-laptop", &spic_dev)) {
dprintk("IRQ: %d - triggering: %d - "
"polarity: %d - shr: %d\n", irq->irq.interrupts[0],
@@ -3539,7 +3554,8 @@ static int sony_pic_add(struct acpi_devi
if (result)
goto err_disable_device;

- result = sysfs_create_group(&sony_pf_device->dev.kobj,
&spic_attribute_group);
+ result = sysfs_create_group(&sony_pf_device->dev.kobj,
+ &spic_attribute_group);
if (result)
goto err_remove_pf;

#22 lore raw

PATCH RESEND v2 10/14 sony-laptop: code style fixes

In reply to Marco Chiappero

This patch fixes all ERROR and WARNING complains by checkpatch.

---

drivers/platform/x86/sony-laptop.c +94 -78
@@ -63,7 +63,7 @@
 #include <linux/slab.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/sonypi.h>
 #include <linux/sony-laptop.h>
 #include <linux/rfkill.h>
@@ -377,11 +377,13 @@ static void sony_laptop_report_input_eve
 
 	default:
 		if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
-			dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
+			dprintk("sony_laptop_report_input_event, "
+				"event not known: %d\n", event);
 			break;
 		}
 		if (sony_laptop_input_index[event] != -1) {
-			kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]];
+			int index = sony_laptop_input_index[event];
+			kp.key = sony_laptop_input_keycode_map[index];
 			if (kp.key != KEY_UNKNOWN)
 				kp.dev = key_dev;
 		}
@@ -565,12 +567,12 @@ static int sony_pf_add(void)
 
 	return 0;
 
-      out_platform_alloced:
+out_platform_alloced:
 	platform_device_put(sony_pf_device);
 	sony_pf_device = NULL;
-      out_platform_registered:
+out_platform_registered:
 	platform_driver_unregister(&sony_pf_driver);
-      out:
+out:
 	atomic_dec(&sony_pf_users);
 	return ret;
 }
@@ -622,7 +624,8 @@ struct sony_nc_value {
 		.acpiset	= _setters, \
 		.validate	= _validate, \
 		.debug		= _debug, \
-		.devattr	= __ATTR(_name, 0, sony_nc_sysfs_show, sony_nc_sysfs_store), \
+		.devattr	= __ATTR(_name, 0, sony_nc_sysfs_show, \
+						sony_nc_sysfs_store), \
 	}
 
 #define SNC_HANDLE_NULL	{ .name = NULL }
@@ -664,7 +667,8 @@ static struct sony_nc_value sony_nc_valu
 	SNC_HANDLE(brightness_default, snc_brightness_def_get,
 			snc_brightness_def_set, brightness_default_validate, 0),
 	SNC_HANDLE(fnkey, snc_fnkey_get, NULL, NULL, 0),
-	SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
+	SNC_HANDLE(cdpower, snc_cdpower_get, snc_cdpower_set,
+			boolean_validate, 0),
 	SNC_HANDLE(audiopower, snc_audiopower_get, snc_audiopower_set,
 			boolean_validate, 0),
 	SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set,
@@ -684,7 +688,7 @@ static struct sony_nc_value sony_nc_valu
 };
 
 static acpi_handle sony_nc_acpi_handle;
-static struct acpi_device *sony_nc_acpi_device = NULL;
+static struct acpi_device *sony_nc_acpi_device;
 
 /*
  * acpi_evaluate_object wrappers
@@ -731,7 +735,8 @@ static int acpi_callsetfunc(acpi_handle 
 	if (status == AE_OK) {
 		if (result != NULL) {
 			if (out_obj.type != ACPI_TYPE_INTEGER) {
-				pr_warn("acpi_evaluate_object bad return type\n");
+				pr_warn("acpi_evaluate_object bad "
+					"return type\n");
 				return -1;
 			}
 			*result = out_obj.integer.value;
@@ -944,11 +949,11 @@ static int sony_call_snc_handle_buffer(u
 static int brightness_default_validate(const int direction, const int value)
 {
 	switch (direction) {
-		case SNC_VALIDATE_OUT:
-			return value - 1;
-		case SNC_VALIDATE_IN:
-			if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
-				return value + 1;
+	case SNC_VALIDATE_OUT:
+		return value - 1;
+	case SNC_VALIDATE_IN:
+		if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
+			return value + 1;
 	}
 	return -EINVAL;
 }
@@ -970,8 +975,9 @@ static int boolean_validate(const int di
 /*
  * Sysfs show/store common to all sony_nc_values
  */
-static ssize_t sony_nc_sysfs_show(struct device *dev, struct device_attribute *attr,
-			      char *buffer)
+static ssize_t sony_nc_sysfs_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buffer)
 {
 	unsigned int value;
 	struct sony_nc_value *item =
@@ -1012,7 +1018,8 @@ static ssize_t sony_nc_sysfs_store(struc
 	if (value < 0)
 		return value;
 
-	if (acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, value, NULL) < 0)
+	if (acpi_callsetfunc(sony_nc_acpi_handle,
+				*item->acpiset, value, NULL) < 0)
 		return -EIO;
 	item->value = value;
 	item->valid = 1;
@@ -1290,9 +1297,9 @@ static void sony_nc_rfkill_update(void)
 			continue;
 
 		if (hwblock) {
-			if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
-				/* we already know we're blocked */
-			}
+			if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
+				/* we already know we're blocked */ ;
+
 			continue;
 		}
 
@@ -1886,7 +1893,8 @@ static int sony_nc_add(struct acpi_devic
 
 	/* read device status */
 	result = acpi_bus_get_status(device);
-	/* bail IFF the above call was successful and the device is not present */
+	/* bail IFF the above call was successful
+	   and the device is not present */
 	if (!result && !device->status.present) {
 		dprintk("Device not present\n");
 		result = -ENODEV;
@@ -1930,11 +1938,11 @@ static int sony_nc_add(struct acpi_devic
 		goto outsnc;
 	}
 
-	if (acpi_video_backlight_support()) {
-		pr_info("brightness ignored, must be controlled by ACPI video driver\n");
-	} else {
+	if (acpi_video_backlight_support())
+		pr_info("brightness ignored, must be "
+			"controlled by ACPI video driver\n");
+	else
 		sony_nc_backlight_setup();
-	}
 
 	/* create sony_pf sysfs attributes related to the SNC device */
 	for (item = sony_nc_values; item->name; ++item) {
@@ -1977,21 +1985,21 @@ static int sony_nc_add(struct acpi_devic
 
 	return 0;
 
-      out_sysfs:
-	for (item = sony_nc_values; item->name; ++item) {
+out_sysfs:
+	for (item = sony_nc_values; item->name; ++item)
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
-	}
+
 	sony_nc_backlight_cleanup();
 
 	sony_laptop_remove_input();
 
-      outsnc:
+outsnc:
 	sony_nc_handles_cleanup(sony_pf_device);
 
-      outpresent:
+outpresent:
 	sony_pf_remove();
 
-      outwalk:
+outwalk:
 	return result;
 }
 
@@ -2004,9 +2012,8 @@ static int sony_nc_remove(struct acpi_de
 
 	sony_nc_acpi_device = NULL;
 
-	for (item = sony_nc_values; item->name; ++item) {
+	for (item = sony_nc_values; item->name; ++item)
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
-	}
 
 	sony_pf_remove();
 	sony_laptop_remove_input();
@@ -2387,11 +2394,14 @@ static u8 sony_pic_call3(u8 dev, u8 fn, 
 {
 	u8 v1;
 
-	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
+	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
+			ITERATIONS_LONG);
 	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
-	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
+	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
+			ITERATIONS_LONG);
 	outb(fn, spic_dev.cur_ioport->io1.minimum);
-	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
+	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
+			ITERATIONS_LONG);
 	outb(v, spic_dev.cur_ioport->io1.minimum);
 	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
 	dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n",
@@ -2505,19 +2515,19 @@ out:
 /* the rest don't need a loop until not 0xff */
 #define SONYPI_CAMERA_AGC			6
 #define SONYPI_CAMERA_AGC_MASK			0x30
-#define SONYPI_CAMERA_SHUTTER_MASK 		0x7
+#define SONYPI_CAMERA_SHUTTER_MASK		0x7
 
 #define SONYPI_CAMERA_SHUTDOWN_REQUEST		7
 #define SONYPI_CAMERA_CONTROL			0x10
 
-#define SONYPI_CAMERA_STATUS 			7
-#define SONYPI_CAMERA_STATUS_READY 		0x2
+#define SONYPI_CAMERA_STATUS			7
+#define SONYPI_CAMERA_STATUS_READY		0x2
 #define SONYPI_CAMERA_STATUS_POSITION		0x4
 
-#define SONYPI_DIRECTION_BACKWARDS 		0x4
+#define SONYPI_DIRECTION_BACKWARDS		0x4
 
-#define SONYPI_CAMERA_REVISION 			8
-#define SONYPI_CAMERA_ROMVERSION 		9
+#define SONYPI_CAMERA_REVISION			8
+#define SONYPI_CAMERA_ROMVERSION		9
 
 static int __sony_pic_camera_ready(void)
 {
@@ -2559,14 +2569,14 @@ static int __sony_pic_camera_on(void)
 
 	for (j = 5; j > 0; j--) {
 
-		for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
-			msleep(10);
+		for (x = 0; x < 50 && sony_pic_call2(0x91, 0x1); x++)
+			msleep(20);
 		sony_pic_call1(0x93);
 
-		for (i = 400; i > 0; i--) {
+		for (i = 200; i > 0; i--) {
 			if (__sony_pic_camera_ready())
 				break;
-			msleep(10);
+			msleep(20);
 		}
 		if (i)
 			break;
@@ -2601,28 +2611,28 @@ int sony_pic_camera_command(int command,
 			__sony_pic_camera_off();
 		break;
 	case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
-		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS, value),
-				ITERATIONS_SHORT);
+		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_BRIGHTNESS,
+				value),	ITERATIONS_SHORT);
 		break;
 	case SONY_PIC_COMMAND_SETCAMERACONTRAST:
-		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST, value),
-				ITERATIONS_SHORT);
+		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_CONTRAST,
+				value),	ITERATIONS_SHORT);
 		break;
 	case SONY_PIC_COMMAND_SETCAMERAHUE:
 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_HUE, value),
 				ITERATIONS_SHORT);
 		break;
 	case SONY_PIC_COMMAND_SETCAMERACOLOR:
-		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR, value),
-				ITERATIONS_SHORT);
+		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_COLOR,
+				value),	ITERATIONS_SHORT);
 		break;
 	case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
-		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS, value),
-				ITERATIONS_SHORT);
+		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_SHARPNESS,
+				value),	ITERATIONS_SHORT);
 		break;
 	case SONY_PIC_COMMAND_SETCAMERAPICTURE:
-		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE, value),
-				ITERATIONS_SHORT);
+		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
+				value),	ITERATIONS_SHORT);
 		break;
 	case SONY_PIC_COMMAND_SETCAMERAAGC:
 		wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_AGC, value),
@@ -3089,7 +3099,8 @@ sony_pic_read_possible_resource(struct a
 	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
 		{
 			/* start IO enumeration */
-			struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
+			struct sony_pic_ioport *ioport =
+					kzalloc(sizeof(*ioport), GFP_KERNEL);
 			if (!ioport)
 				return AE_ERROR;
 
@@ -3137,7 +3148,8 @@ sony_pic_read_possible_resource(struct a
 		{
 			struct acpi_resource_io *io = &resource->data.io;
 			struct sony_pic_ioport *ioport =
-				list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
+				list_first_entry(&dev->ioports,
+						struct sony_pic_ioport, list);
 			if (!io) {
 				dprintk("Blank IO resource\n");
 				return AE_OK;
@@ -3145,16 +3157,17 @@ sony_pic_read_possible_resource(struct a
 
 			if (!ioport->io1.minimum) {
 				memcpy(&ioport->io1, io, sizeof(*io));
-				dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
+				dprintk("IO1 at 0x%.4x (0x%.2x)\n",
+						ioport->io1.minimum,
 						ioport->io1.address_length);
-			}
-			else if (!ioport->io2.minimum) {
+			} else if (!ioport->io2.minimum) {
 				memcpy(&ioport->io2, io, sizeof(*io));
-				dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
+				dprintk("IO2 at 0x%.4x (0x%.2x)\n",
+						ioport->io2.minimum,
 						ioport->io2.address_length);
-			}
-			else {
-				pr_err("Unknown SPIC Type, more than 2 IO Ports\n");
+			} else {
+				pr_err("Unknown SPIC Type, "
+					"more than 2 IO Ports\n");
 				return AE_ERROR;
 			}
 			return AE_OK;
@@ -3477,24 +3490,26 @@ static int sony_pic_add(struct acpi_devi
 			/* Type 1 have 2 ioports */
 			if (io->io2.minimum) {
 				if (request_region(io->io2.minimum,
-						io->io2.address_length,
-						"Sony Programmable I/O Device")) {
-					dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
-							io->io2.minimum, io->io2.maximum,
+					io->io2.address_length,
+					"Sony Programmable I/O Device")) {
+					dprintk("I/O port2: 0x%.4x (0x%.4x) "
+							"+ 0x%.2x\n",
+							io->io2.minimum,
+							io->io2.maximum,
 							io->io2.address_length);
 					spic_dev.cur_ioport = io;
 					break;
-				}
-				else {
+				} else {
 					dprintk("Unable to get I/O port2: "
-							"0x%.4x (0x%.4x) + 0x%.2x\n",
-							io->io2.minimum, io->io2.maximum,
+							"0x%.4x (0x%.4x) "
+							"+ 0x%.2x\n",
+							io->io2.minimum,
+							io->io2.maximum,
 							io->io2.address_length);
 					release_region(io->io1.minimum,
 							io->io1.address_length);
 				}
-			}
-			else {
+			} else {
 				spic_dev.cur_ioport = io;
 				break;
 			}
@@ -3509,7 +3524,7 @@ static int sony_pic_add(struct acpi_devi
 	/* request IRQ */
 	list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
 		if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
-					IRQF_DISABLED, "sony-laptop", &spic_dev)) {
+				IRQF_DISABLED, "sony-laptop", &spic_dev)) {
 			dprintk("IRQ: %d - triggering: %d - "
 					"polarity: %d - shr: %d\n",
 					irq->irq.interrupts[0],
@@ -3539,7 +3554,8 @@ static int sony_pic_add(struct acpi_devi
 	if (result)
 		goto err_disable_device;
 
-	result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
+	result = sysfs_create_group(&sony_pf_device->dev.kobj,
+					&spic_attribute_group);
 	if (result)
 		goto err_remove_pf;
 
#23 lore raw

PATCH v2 11/14 sony-laptop: keyboard backlight support extended to newer Vaios

In reply to Marco Chiappero

Added support for handle 0x0143 (Vaio SA/SB/SC, CA/CB) and improved the keyboard backlight code, removing the struct "kbd_backlight" in favor of "struct snc_kbdbl_device". Minor corrections are also included.

---

drivers/platform/x86/sony-laptop.c +47 -44
@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor,
 		 "default is -1 (automatic)");
 #endif
 
-static int kbd_backlight;	/* = 1 */
+static int kbd_backlight;	/* = 0 */
 module_param(kbd_backlight, int, 0444);
 MODULE_PARM_DESC(kbd_backlight,
 		 "set this to 0 to disable keyboard backlight, "
@@ -140,7 +140,6 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
 		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
 		 "(default: 0)");
 
-static void sony_nc_kbd_backlight_resume(void);
 
 enum sony_nc_rfkill {
 	SONY_WIFI,
@@ -1362,37 +1361,31 @@ static int sony_nc_rfkill_setup(struct a
 }
 
 /* Keyboard backlight feature */
-#define KBDBL_HANDLER	0x137
-#define KBDBL_PRESENT	0xB00
-#define	SET_MODE	0xC00
-#define SET_STATE	0xD00
-#define SET_TIMEOUT	0xE00
-
-struct kbd_backlight {
-	int mode;
-	int timeout;
+static struct snc_kbdbl_device {
+	unsigned int handle;
+	unsigned int base;
+	unsigned int mode;
+	unsigned int timeout;
 	struct device_attribute mode_attr;
 	struct device_attribute timeout_attr;
-};
-
-static struct kbd_backlight *kbdbl_handle;
+} *snc_kbdbl;
 
-static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
+static int __sony_nc_kbd_backlight_mode_set(u8 value)
 {
 	unsigned int result;
 
 	if (value > 1)
 		return -EINVAL;
 
-	if (sony_call_snc_handle(KBDBL_HANDLER,
-				(value << 0x10) | SET_MODE, &result))
+	if (sony_call_snc_handle(snc_kbdbl->handle, (value << 0x10) |
+				(snc_kbdbl->base), &result))
 		return -EIO;
 
-	/* Try to turn the light on/off immediately */
-	sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE,
-			&result);
+	snc_kbdbl->mode = value;
 
-	kbdbl_handle->mode = value;
+	/* Try to turn the light on/off immediately */
+	sony_call_snc_handle(snc_kbdbl->handle, (value << 0x10) |
+				(snc_kbdbl->base + 0x100), &result);
 
 	return 0;
 }
@@ -1421,7 +1414,9 @@ static ssize_t sony_nc_kbd_backlight_mod
 		struct device_attribute *attr, char *buffer)
 {
 	ssize_t count = 0;
-	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode);
+
+	count = snprintf(buffer, PAGE_SIZE, "%d\n", snc_kbdbl->mode);
+
 	return count;
 }
 
@@ -1432,11 +1427,11 @@ static int __sony_nc_kbd_backlight_timeo
 	if (value > 3)
 		return -EINVAL;
 
-	if (sony_call_snc_handle(KBDBL_HANDLER,
-				(value << 0x10) | SET_TIMEOUT, &result))
+	if (sony_call_snc_handle(snc_kbdbl->handle, (value << 0x10) |
+				(snc_kbdbl->base + 0x200), &result))
 		return -EIO;
 
-	kbdbl_handle->timeout = value;
+	snc_kbdbl->timeout = value;
 
 	return 0;
 }
@@ -1465,85 +1460,111 @@ static ssize_t sony_nc_kbd_backlight_tim
 		struct device_attribute *attr, char *buffer)
 {
 	ssize_t count = 0;
-	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout);
+
+	count = snprintf(buffer, PAGE_SIZE, "%d\n", snc_kbdbl->timeout);
+
 	return count;
 }
 
-static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
+static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
+					unsigned int handle)
 {
-	unsigned int result;
+	unsigned int result, base_cmd;
+	bool found = false;
 
-	if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
-		return 0;
-	if (!(result & 0x02))
+	/* verify the kbd backlight presence, some models do not have it */
+	if (handle == 0x0137) {
+		if (sony_call_snc_handle(handle, 0x0B00, &result))
+			return -EIO;
+
+		found = !!(result & 0x02);
+		base_cmd = 0x0C00;
+	} else {
+		if (sony_call_snc_handle(handle, 0x0100, &result))
+			return -EIO;
+
+		found = result & 0x01;
+		base_cmd = 0x4000;
+	}
+
+	if (!found) {
+		dprintk("no backlight keyboard found\n");
 		return 0;
+	}
 
-	kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL);
-	if (!kbdbl_handle)
+	snc_kbdbl = kzalloc(sizeof(*snc_kbdbl), GFP_KERNEL);
+	if (!snc_kbdbl)
 		return -ENOMEM;
 
-	sysfs_attr_init(&kbdbl_handle->mode_attr.attr);
-	kbdbl_handle->mode_attr.attr.name = "kbd_backlight";
-	kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
-	kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show;
-	kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store;
-
-	sysfs_attr_init(&kbdbl_handle->timeout_attr.attr);
-	kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout";
-	kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
-	kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
-	kbdbl_handle->timeout_attr.store =

sony_nc_kbd_backlight_timeout_store;
+ sysfs_attr_init(&snc_kbdbl->mode_attr.attr);
+ snc_kbdbl->mode_attr.attr.name = "kbd_backlight";
+ snc_kbdbl->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
+ snc_kbdbl->mode_attr.show = sony_nc_kbd_backlight_mode_show;
+ snc_kbdbl->mode_attr.store = sony_nc_kbd_backlight_mode_store;
+
+ sysfs_attr_init(&snc_kbdbl->timeout_attr.attr);
+ snc_kbdbl->timeout_attr.attr.name = "kbd_backlight_timeout";
+ snc_kbdbl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
+ snc_kbdbl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
+ snc_kbdbl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;

- if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr))
+ if (device_create_file(&pd->dev, &snc_kbdbl->mode_attr))
goto outkzalloc;

- if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr))
+ if (device_create_file(&pd->dev, &snc_kbdbl->timeout_attr))
goto outmode;

+ snc_kbdbl->handle = handle;
+ snc_kbdbl->base = base_cmd;
+
__sony_nc_kbd_backlight_mode_set(kbd_backlight); __sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);

return 0;

outmode:
- device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
+ device_remove_file(&pd->dev, &snc_kbdbl->mode_attr);
outkzalloc:
- kfree(kbdbl_handle);
- kbdbl_handle = NULL;
+ kfree(snc_kbdbl);
+ snc_kbdbl = NULL;
return -1;
}

static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) {
- if (kbdbl_handle) {
+ if (snc_kbdbl) {
unsigned int result;

- device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
- device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
+ device_remove_file(&pd->dev, &snc_kbdbl->mode_attr);
+ device_remove_file(&pd->dev, &snc_kbdbl->timeout_attr);

/* restore the default hw behaviour */
- sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result);
- sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result);
+ sony_call_snc_handle(snc_kbdbl->handle,
+ snc_kbdbl->base | 0x10000, &result);
+ sony_call_snc_handle(snc_kbdbl->handle,
+ snc_kbdbl->base + 0x200, &result);

- kfree(kbdbl_handle);
+ kfree(snc_kbdbl);
+ snc_kbdbl = NULL;
}
return 0;
}

static void sony_nc_kbd_backlight_resume(void)
{
- unsigned int ignore = 0;
+ unsigned int result;

- if (!kbdbl_handle)
+ if (!snc_kbdbl)
return;

- if (kbdbl_handle->mode == 0)
- sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore);
-
- if (kbdbl_handle->timeout != 0)
- sony_call_snc_handle(KBDBL_HANDLER,
- (kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
- &ignore);
+ if (snc_kbdbl->mode == 0)
+ sony_call_snc_handle(snc_kbdbl->handle,
+ snc_kbdbl->base, &result);
+
+ if (snc_kbdbl->timeout != 0)
+ sony_call_snc_handle(snc_kbdbl->handle,
+ (snc_kbdbl->base + 0x200) |
+ (snc_kbdbl->timeout << 0x10), &result);
}

static void sony_nc_backlight_ng_read_limits(unsigned int handle,
@@ -1692,7 +1713,8 @@ static int sony_nc_handles_setup(struct
ret = sony_nc_function_setup(handle); break;
case 0x0137:
- ret = sony_nc_kbd_backlight_setup(pd);
+ case 0x0143:
+ ret = sony_nc_kbd_backlight_setup(pd, handle);
case 0x0124:
case 0x0135:
ret = sony_nc_rfkill_setup(sony_nc_acpi_device);
@@ -1737,6 +1759,7 @@ static int sony_nc_handles_cleanup(struc

switch (handle) {
case 0x0137:
+ case 0x0143:
sony_nc_kbd_backlight_cleanup(pd);
case 0x0124:
case 0x0135:
@@ -1783,6 +1806,7 @@ static int sony_nc_handles_resume(void)
sony_nc_function_setup(handle); break;
case 0x0137: /* kbd + als */
+ case 0x0143:
sony_nc_kbd_backlight_resume(); break;
case 0x0124:

#24 lore raw

PATCH RESEND v2 11/14 sony-laptop: keyboard backlight support extended to newer Vaios

In reply to Marco Chiappero

Added support for handle 0x0143 (Vaio SA/SB/SC, CA/CB) and improved the keyboard backlight code, removing the struct "kbd_backlight" in favor of "struct snc_kbdbl_device". Minor corrections are also included.

---

drivers/platform/x86/sony-laptop.c +89 -65
@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor,
 		 "default is -1 (automatic)");
 #endif
 
-static int kbd_backlight;	/* = 1 */
+static int kbd_backlight;	/* = 0 */
 module_param(kbd_backlight, int, 0444);
 MODULE_PARM_DESC(kbd_backlight,
 		 "set this to 0 to disable keyboard backlight, "
@@ -140,7 +140,6 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
 		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
 		 "(default: 0)");
 
-static void sony_nc_kbd_backlight_resume(void);
 
 enum sony_nc_rfkill {
 	SONY_WIFI,
@@ -1362,37 +1361,31 @@ static int sony_nc_rfkill_setup(struct a
 }
 
 /* Keyboard backlight feature */
-#define KBDBL_HANDLER	0x137
-#define KBDBL_PRESENT	0xB00
-#define	SET_MODE	0xC00
-#define SET_STATE	0xD00
-#define SET_TIMEOUT	0xE00
-
-struct kbd_backlight {
-	int mode;
-	int timeout;
+static struct snc_kbdbl_device {
+	unsigned int handle;
+	unsigned int base;
+	unsigned int mode;
+	unsigned int timeout;
 	struct device_attribute mode_attr;
 	struct device_attribute timeout_attr;
-};
-
-static struct kbd_backlight *kbdbl_handle;
+} *snc_kbdbl;
 
-static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
+static int __sony_nc_kbd_backlight_mode_set(u8 value)
 {
 	unsigned int result;
 
 	if (value > 1)
 		return -EINVAL;
 
-	if (sony_call_snc_handle(KBDBL_HANDLER,
-				(value << 0x10) | SET_MODE, &result))
+	if (sony_call_snc_handle(snc_kbdbl->handle, (value << 0x10) |
+				(snc_kbdbl->base), &result))
 		return -EIO;
 
-	/* Try to turn the light on/off immediately */
-	sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE,
-			&result);
+	snc_kbdbl->mode = value;
 
-	kbdbl_handle->mode = value;
+	/* Try to turn the light on/off immediately */
+	sony_call_snc_handle(snc_kbdbl->handle, (value << 0x10) |
+				(snc_kbdbl->base + 0x100), &result);
 
 	return 0;
 }
@@ -1421,7 +1414,9 @@ static ssize_t sony_nc_kbd_backlight_mod
 		struct device_attribute *attr, char *buffer)
 {
 	ssize_t count = 0;
-	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode);
+
+	count = snprintf(buffer, PAGE_SIZE, "%d\n", snc_kbdbl->mode);
+
 	return count;
 }
 
@@ -1432,11 +1427,11 @@ static int __sony_nc_kbd_backlight_timeo
 	if (value > 3)
 		return -EINVAL;
 
-	if (sony_call_snc_handle(KBDBL_HANDLER,
-				(value << 0x10) | SET_TIMEOUT, &result))
+	if (sony_call_snc_handle(snc_kbdbl->handle, (value << 0x10) |
+				(snc_kbdbl->base + 0x200), &result))
 		return -EIO;
 
-	kbdbl_handle->timeout = value;
+	snc_kbdbl->timeout = value;
 
 	return 0;
 }
@@ -1465,85 +1460,111 @@ static ssize_t sony_nc_kbd_backlight_tim
 		struct device_attribute *attr, char *buffer)
 {
 	ssize_t count = 0;
-	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout);
+
+	count = snprintf(buffer, PAGE_SIZE, "%d\n", snc_kbdbl->timeout);
+
 	return count;
 }
 
-static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
+static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
+					unsigned int handle)
 {
-	unsigned int result;
+	unsigned int result, base_cmd;
+	bool found = false;
 
-	if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
-		return 0;
-	if (!(result & 0x02))
+	/* verify the kbd backlight presence, some models do not have it */
+	if (handle == 0x0137) {
+		if (sony_call_snc_handle(handle, 0x0B00, &result))
+			return -EIO;
+
+		found = !!(result & 0x02);
+		base_cmd = 0x0C00;
+	} else {
+		if (sony_call_snc_handle(handle, 0x0100, &result))
+			return -EIO;
+
+		found = result & 0x01;
+		base_cmd = 0x4000;
+	}
+
+	if (!found) {
+		dprintk("no backlight keyboard found\n");
 		return 0;
+	}
 
-	kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL);
-	if (!kbdbl_handle)
+	snc_kbdbl = kzalloc(sizeof(*snc_kbdbl), GFP_KERNEL);
+	if (!snc_kbdbl)
 		return -ENOMEM;
 
-	sysfs_attr_init(&kbdbl_handle->mode_attr.attr);
-	kbdbl_handle->mode_attr.attr.name = "kbd_backlight";
-	kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
-	kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show;
-	kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store;
-
-	sysfs_attr_init(&kbdbl_handle->timeout_attr.attr);
-	kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout";
-	kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
-	kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
-	kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
+	sysfs_attr_init(&snc_kbdbl->mode_attr.attr);
+	snc_kbdbl->mode_attr.attr.name = "kbd_backlight";
+	snc_kbdbl->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
+	snc_kbdbl->mode_attr.show = sony_nc_kbd_backlight_mode_show;
+	snc_kbdbl->mode_attr.store = sony_nc_kbd_backlight_mode_store;
+
+	sysfs_attr_init(&snc_kbdbl->timeout_attr.attr);
+	snc_kbdbl->timeout_attr.attr.name = "kbd_backlight_timeout";
+	snc_kbdbl->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
+	snc_kbdbl->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
+	snc_kbdbl->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
 
-	if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr))
+	if (device_create_file(&pd->dev, &snc_kbdbl->mode_attr))
 		goto outkzalloc;
 
-	if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr))
+	if (device_create_file(&pd->dev, &snc_kbdbl->timeout_attr))
 		goto outmode;
 
+	snc_kbdbl->handle = handle;
+	snc_kbdbl->base = base_cmd;
+
 	__sony_nc_kbd_backlight_mode_set(kbd_backlight);
 	__sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
 
 	return 0;
 
 outmode:
-	device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
+	device_remove_file(&pd->dev, &snc_kbdbl->mode_attr);
 outkzalloc:
-	kfree(kbdbl_handle);
-	kbdbl_handle = NULL;
+	kfree(snc_kbdbl);
+	snc_kbdbl = NULL;
 	return -1;
 }
 
 static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
 {
-	if (kbdbl_handle) {
+	if (snc_kbdbl) {
 		unsigned int result;
 
-		device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
-		device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
+		device_remove_file(&pd->dev, &snc_kbdbl->mode_attr);
+		device_remove_file(&pd->dev, &snc_kbdbl->timeout_attr);
 
 		/* restore the default hw behaviour */
-		sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result);
-		sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result);
+		sony_call_snc_handle(snc_kbdbl->handle,
+				snc_kbdbl->base | 0x10000, &result);
+		sony_call_snc_handle(snc_kbdbl->handle,
+				snc_kbdbl->base + 0x200, &result);
 
-		kfree(kbdbl_handle);
+		kfree(snc_kbdbl);
+		snc_kbdbl = NULL;
 	}
 	return 0;
 }
 
 static void sony_nc_kbd_backlight_resume(void)
 {
-	unsigned int ignore = 0;
+	unsigned int result;
 
-	if (!kbdbl_handle)
+	if (!snc_kbdbl)
 		return;
 
-	if (kbdbl_handle->mode == 0)
-		sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore);
-
-	if (kbdbl_handle->timeout != 0)
-		sony_call_snc_handle(KBDBL_HANDLER,
-				(kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
-				&ignore);
+	if (snc_kbdbl->mode == 0)
+		sony_call_snc_handle(snc_kbdbl->handle,
+				snc_kbdbl->base, &result);
+
+	if (snc_kbdbl->timeout != 0)
+		sony_call_snc_handle(snc_kbdbl->handle,
+				(snc_kbdbl->base + 0x200) |
+				(snc_kbdbl->timeout << 0x10), &result);
 }
 
 static void sony_nc_backlight_ng_read_limits(unsigned int handle,
@@ -1692,7 +1713,8 @@ static int sony_nc_handles_setup(struct 
 			ret = sony_nc_function_setup(handle);
 			break;
 		case 0x0137:
-			ret = sony_nc_kbd_backlight_setup(pd);
+		case 0x0143:
+			ret = sony_nc_kbd_backlight_setup(pd, handle);
 		case 0x0124:
 		case 0x0135:
 			ret = sony_nc_rfkill_setup(sony_nc_acpi_device);
@@ -1737,6 +1759,7 @@ static int sony_nc_handles_cleanup(struc
 
 		switch (handle) {
 		case 0x0137:
+		case 0x0143:
 			sony_nc_kbd_backlight_cleanup(pd);
 		case 0x0124:
 		case 0x0135:
@@ -1783,6 +1806,7 @@ static int sony_nc_handles_resume(void)
 			sony_nc_function_setup(handle);
 			break;
 		case 0x0137: /* kbd + als */
+		case 0x0143:
 			sony_nc_kbd_backlight_resume();
 			break;
 		case 0x0124:
#25 lore raw

PATCH v2 12/14 sony-laptop: rfkill improvements

In reply to Marco Chiappero

This patch introduces some rfkill improvements in terms of both code cleaning and support extension. More precisely:

- removed any handle autodetection inside the setup function as it's now provided by the caller
- rfkill type now persistent, using the hardware capability of storing the wireless devices power state
- added support for newer WWAN modules
- removed some global variables now included in a few struct for a cleaner code. These structs have been placed close to the rfkill functions for better readability
- minor code improvements

---

drivers/platform/x86/sony-laptop.c +0 -11
@@ -141,19 +141,6 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
 		 "(default: 0)");
 
 
-enum sony_nc_rfkill {
-	SONY_WIFI,
-	SONY_BLUETOOTH,
-	SONY_WWAN,
-	SONY_WIMAX,
-	N_SONY_RFKILL,
-};
-
-static unsigned int sony_rfkill_handle;
-static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
-static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700,

0x900};
-static void sony_nc_rfkill_update(void);
-
/*********** Input Devices ***********/

#define SONY_LAPTOP_BUF_SIZE 128
@@ -1204,30 +1191,51 @@ static int sony_nc_hotkeys_decode(unsign
return ret;
}

+enum sony_nc_rfkill {
+ SONY_WIFI,
+ SONY_BLUETOOTH,
+ SONY_WWAN,
+ SONY_WIMAX,
+ N_SONY_RFKILL,
+};
+struct snc_rfkill_data {
+ unsigned int handle;
+ struct rfkill *devices[N_SONY_RFKILL];
+ const unsigned int address[N_SONY_RFKILL];
+};
+static struct snc_rfkill_data snc_rfkill = {
+ 0, {NULL}, {0x300, 0x500, 0x700, 0x900}
+};
+
static void sony_nc_rfkill_cleanup(void)
{
int i;

for (i = 0; i < N_SONY_RFKILL; i++) {
- if (sony_rfkill_devices[i]) {
- rfkill_unregister(sony_rfkill_devices[i]);
- rfkill_destroy(sony_rfkill_devices[i]);
+ if (snc_rfkill.devices[i]) {
+ rfkill_unregister(snc_rfkill.devices[i]);
+ rfkill_destroy(snc_rfkill.devices[i]);
}
}
}

static int sony_nc_rfkill_set(void *data, bool blocked) {
- unsigned int result;
- unsigned int argument = sony_rfkill_address[(long) data] + 0x100;
+ unsigned int result, argument = snc_rfkill.address[(long) data];

+ /* do not force an already set state */
+ sony_call_snc_handle(snc_rfkill.handle, argument, &result);
+ if ((result & 0x1) == !blocked)
+ return 0;
+
+ argument += 0x100;
if (!blocked)
argument |= 0xff0000;

- return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
+ return sony_call_snc_handle(snc_rfkill.handle, argument, &result);
}

-static const struct rfkill_ops sony_rfkill_ops = { +static const struct rfkill_ops snc_rfkill_ops = {
.set_block = sony_nc_rfkill_set,
};

@@ -1239,7 +1247,7 @@ static int sony_nc_setup_rfkill(struct a
enum rfkill_type type;
const char *name;
unsigned int result;
- bool hwblock;
+ bool hwblock, swblock;

switch (nc_type) {
case SONY_WIFI:
@@ -1263,12 +1271,19 @@ static int sony_nc_setup_rfkill(struct a
}

rfk = rfkill_alloc(name, &device->dev, type,
- &sony_rfkill_ops, (void *)nc_type);
+ &snc_rfkill_ops, (void *)nc_type);
if (!rfk)
return -ENOMEM;

- sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
+ sony_call_snc_handle(snc_rfkill.handle, 0x200, &result);
hwblock = !(result & 0x1);
+
+ result = 0;
+ sony_call_snc_handle(snc_rfkill.handle, snc_rfkill.address[nc_type],
+ &result);
+ swblock = !(result & 0x2);
+
+ rfkill_init_sw_state(rfk, swblock);
rfkill_set_hw_state(rfk, hwblock);

err = rfkill_register(rfk);
@@ -1276,7 +1291,7 @@ static int sony_nc_setup_rfkill(struct a
rfkill_destroy(rfk);
return err;
}
- sony_rfkill_devices[nc_type] = rfk;
+ snc_rfkill.devices[nc_type] = rfk;
return err;
}

@@ -1284,51 +1299,35 @@ static void sony_nc_rfkill_update(void)
{
enum sony_nc_rfkill i;
unsigned int result;
- bool hwblock;
+ bool hwblock, swblock;

- sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
+ sony_call_snc_handle(snc_rfkill.handle, 0x200, &result);
hwblock = !(result & 0x1);

for (i = 0; i < N_SONY_RFKILL; i++) {
- unsigned int argument = sony_rfkill_address[i];
+ unsigned int argument = snc_rfkill.address[i];

- if (!sony_rfkill_devices[i])
+ if (!snc_rfkill.devices[i])
continue;

- if (hwblock) {
- if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
- /* we already know we're blocked */ ;
-
- continue;
- }
+ sony_call_snc_handle(snc_rfkill.handle, argument, &result);
+ swblock = !(result & 0x2);

- sony_call_snc_handle(sony_rfkill_handle, argument, &result);
- rfkill_set_states(sony_rfkill_devices[i],
- !(result & 0xf), false);
+ rfkill_set_states(snc_rfkill.devices[i], swblock, hwblock);
}
}

-static int sony_nc_rfkill_setup(struct acpi_device *device) +static int sony_nc_rfkill_setup(struct acpi_device *device, unsigned int handle)
{
#define RFKILL_BUFF_SIZE 8
u8 dev_code, i, buff[RFKILL_BUFF_SIZE] = { 0 };
- int offset;

- offset = sony_find_snc_handle(0x124);
- if (offset == -1) {
- offset = sony_find_snc_handle(0x135);
- if (offset == -1)
- return 0;
- else
- sony_rfkill_handle = 0x135;
- } else
- sony_rfkill_handle = 0x124;
- dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
+ snc_rfkill.handle = handle;

/* need to read the whole buffer returned by the acpi call to SN06
* here otherwise we may miss some features
*/
- if (sony_call_snc_handle_buffer(sony_rfkill_handle, 0x000,
+ if (sony_call_snc_handle_buffer(snc_rfkill.handle, 0x000,
buff, RFKILL_BUFF_SIZE) < 0)
return -EIO;

@@ -1341,19 +1340,38 @@ static int sony_nc_rfkill_setup(struct a
if (dev_code == 0xff)
break;

+ /*
+ known codes:
+

+		   0x00	WLAN
+		   0x10 BLUETOOTH
+		   0x20 WWAN GPRS-EDGE
+		   0x21 WWAN HSDPA
+		   0x22 WWAN EV-DO
+		   0x23 WWAN GPS
+		   0x25	Gobi WWAN no GPS
+		   0x26 Gobi WWAN + GPS
+		   0x28	Gobi WWAN no GPS
+		   0x29 Gobi WWAN + GPS
+		   0x50	Gobi WWAN no GPS
+		   0x51 Gobi WWAN + GPS
+		   0x30	WIMAX
+		   0x70 no SIM card slot
+		   0x71 SIM card slot

+ */
dprintk("Radio devices, looking at 0x%.2x\n", dev_code);

- if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
+ if (dev_code == 0 && !snc_rfkill.devices[SONY_WIFI])
sony_nc_setup_rfkill(device, SONY_WIFI);

- if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
+ if (dev_code == 0x10 && !snc_rfkill.devices[SONY_BLUETOOTH])
sony_nc_setup_rfkill(device, SONY_BLUETOOTH);

- if ((0xf0 & dev_code) == 0x20 &&
- !sony_rfkill_devices[SONY_WWAN])
+ if (((0xf0 & dev_code) == 0x20 || (0xf0 & dev_code) == 0x50) &&
+ !snc_rfkill.devices[SONY_WWAN])
sony_nc_setup_rfkill(device, SONY_WWAN);

- if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
+ if (dev_code == 0x30 && !snc_rfkill.devices[SONY_WIMAX])
sony_nc_setup_rfkill(device, SONY_WIMAX);
}

@@ -1717,7 +1735,7 @@ static int sony_nc_handles_setup(struct
ret = sony_nc_kbd_backlight_setup(pd, handle);
case 0x0124:
case 0x0135:
- ret = sony_nc_rfkill_setup(sony_nc_acpi_device);
+ ret = sony_nc_rfkill_setup(sony_nc_acpi_device, handle);
break;
default:
continue;

#26 lore raw

PATCH RESEND v2 12/14 sony-laptop: rfkill improvements

In reply to Marco Chiappero

This patch introduces some rfkill improvements in terms of both code cleaning and support extension. More precisely:

- removed any handle autodetection inside the setup function as it's now provided by the caller
- rfkill type now persistent, using the hardware capability of storing the wireless devices power state
- added support for newer WWAN modules
- removed some global variables now included in a few struct for a cleaner code. These structs have been placed close to the rfkill functions for better readability
- minor code improvements

---

drivers/platform/x86/sony-laptop.c +74 -56
@@ -141,19 +141,6 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
 		 "(default: 0)");
 
 
-enum sony_nc_rfkill {
-	SONY_WIFI,
-	SONY_BLUETOOTH,
-	SONY_WWAN,
-	SONY_WIMAX,
-	N_SONY_RFKILL,
-};
-
-static unsigned int sony_rfkill_handle;
-static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
-static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
-static void sony_nc_rfkill_update(void);
-
 /*********** Input Devices ***********/
 
 #define SONY_LAPTOP_BUF_SIZE	128
@@ -1204,30 +1191,51 @@ static int sony_nc_hotkeys_decode(unsign
 	return ret;
 }
 
+enum sony_nc_rfkill {
+	SONY_WIFI,
+	SONY_BLUETOOTH,
+	SONY_WWAN,
+	SONY_WIMAX,
+	N_SONY_RFKILL,
+};
+struct snc_rfkill_data {
+	unsigned int handle;
+	struct rfkill *devices[N_SONY_RFKILL];
+	const unsigned int address[N_SONY_RFKILL];
+};
+static struct snc_rfkill_data snc_rfkill = {
+	0, {NULL}, {0x300, 0x500, 0x700, 0x900}
+};
+
 static void sony_nc_rfkill_cleanup(void)
 {
 	int i;
 
 	for (i = 0; i < N_SONY_RFKILL; i++) {
-		if (sony_rfkill_devices[i]) {
-			rfkill_unregister(sony_rfkill_devices[i]);
-			rfkill_destroy(sony_rfkill_devices[i]);
+		if (snc_rfkill.devices[i]) {
+			rfkill_unregister(snc_rfkill.devices[i]);
+			rfkill_destroy(snc_rfkill.devices[i]);
 		}
 	}
 }
 
 static int sony_nc_rfkill_set(void *data, bool blocked)
 {
-	unsigned int result;
-	unsigned int argument = sony_rfkill_address[(long) data] + 0x100;
+	unsigned int result, argument = snc_rfkill.address[(long) data];
 
+	/* do not force an already set state */
+	sony_call_snc_handle(snc_rfkill.handle, argument, &result);
+	if ((result & 0x1) == !blocked)
+		return 0;
+
+	argument += 0x100;
 	if (!blocked)
 		argument |= 0xff0000;
 
-	return sony_call_snc_handle(sony_rfkill_handle, argument, &result);
+	return sony_call_snc_handle(snc_rfkill.handle, argument, &result);
 }
 
-static const struct rfkill_ops sony_rfkill_ops = {
+static const struct rfkill_ops snc_rfkill_ops = {
 	.set_block = sony_nc_rfkill_set,
 };
 
@@ -1239,7 +1247,7 @@ static int sony_nc_setup_rfkill(struct a
 	enum rfkill_type type;
 	const char *name;
 	unsigned int result;
-	bool hwblock;
+	bool hwblock, swblock;
 
 	switch (nc_type) {
 	case SONY_WIFI:
@@ -1263,12 +1271,19 @@ static int sony_nc_setup_rfkill(struct a
 	}
 
 	rfk = rfkill_alloc(name, &device->dev, type,
-			   &sony_rfkill_ops, (void *)nc_type);
+			   &snc_rfkill_ops, (void *)nc_type);
 	if (!rfk)
 		return -ENOMEM;
 
-	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
+	sony_call_snc_handle(snc_rfkill.handle, 0x200, &result);
 	hwblock = !(result & 0x1);
+
+	result = 0;
+	sony_call_snc_handle(snc_rfkill.handle, snc_rfkill.address[nc_type],
+				&result);
+	swblock = !(result & 0x2);
+
+	rfkill_init_sw_state(rfk, swblock);
 	rfkill_set_hw_state(rfk, hwblock);
 
 	err = rfkill_register(rfk);
@@ -1276,7 +1291,7 @@ static int sony_nc_setup_rfkill(struct a
 		rfkill_destroy(rfk);
 		return err;
 	}
-	sony_rfkill_devices[nc_type] = rfk;
+	snc_rfkill.devices[nc_type] = rfk;
 	return err;
 }
 
@@ -1284,51 +1299,35 @@ static void sony_nc_rfkill_update(void)
 {
 	enum sony_nc_rfkill i;
 	unsigned int result;
-	bool hwblock;
+	bool hwblock, swblock;
 
-	sony_call_snc_handle(sony_rfkill_handle, 0x200, &result);
+	sony_call_snc_handle(snc_rfkill.handle, 0x200, &result);
 	hwblock = !(result & 0x1);
 
 	for (i = 0; i < N_SONY_RFKILL; i++) {
-		unsigned int argument = sony_rfkill_address[i];
+		unsigned int argument = snc_rfkill.address[i];
 
-		if (!sony_rfkill_devices[i])
+		if (!snc_rfkill.devices[i])
 			continue;
 
-		if (hwblock) {
-			if (rfkill_set_hw_state(sony_rfkill_devices[i], true))
-				/* we already know we're blocked */ ;
-
-			continue;
-		}
+		sony_call_snc_handle(snc_rfkill.handle, argument, &result);
+		swblock = !(result & 0x2);
 
-		sony_call_snc_handle(sony_rfkill_handle, argument, &result);
-		rfkill_set_states(sony_rfkill_devices[i],
-				  !(result & 0xf), false);
+		rfkill_set_states(snc_rfkill.devices[i], swblock, hwblock);
 	}
 }
 
-static int sony_nc_rfkill_setup(struct acpi_device *device)
+static int sony_nc_rfkill_setup(struct acpi_device *device, unsigned int handle)
 {
 #define	RFKILL_BUFF_SIZE 8
 	u8 dev_code, i, buff[RFKILL_BUFF_SIZE] = { 0 };
-	int offset;
 
-	offset = sony_find_snc_handle(0x124);
-	if (offset == -1) {
-		offset = sony_find_snc_handle(0x135);
-		if (offset == -1)
-			return 0;
-		else
-			sony_rfkill_handle = 0x135;
-	} else
-		sony_rfkill_handle = 0x124;
-	dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
+	snc_rfkill.handle = handle;
 
 	/* need to read the whole buffer returned by the acpi call to SN06
 	 * here otherwise we may miss some features
 	 */
-	if (sony_call_snc_handle_buffer(sony_rfkill_handle, 0x000,
+	if (sony_call_snc_handle_buffer(snc_rfkill.handle, 0x000,
 					buff, RFKILL_BUFF_SIZE) < 0)
 		return -EIO;
 
@@ -1341,19 +1340,38 @@ static int sony_nc_rfkill_setup(struct a
 		if (dev_code == 0xff)
 			break;
 
+		/*
+		   known codes:
+
+		   0x00	WLAN
+		   0x10 BLUETOOTH
+		   0x20 WWAN GPRS-EDGE
+		   0x21 WWAN HSDPA
+		   0x22 WWAN EV-DO
+		   0x23 WWAN GPS
+		   0x25	Gobi WWAN no GPS
+		   0x26 Gobi WWAN + GPS
+		   0x28	Gobi WWAN no GPS
+		   0x29 Gobi WWAN + GPS
+		   0x50	Gobi WWAN no GPS
+		   0x51 Gobi WWAN + GPS
+		   0x30	WIMAX
+		   0x70 no SIM card slot
+		   0x71 SIM card slot
+		*/
 		dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
 
-		if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
+		if (dev_code == 0 && !snc_rfkill.devices[SONY_WIFI])
 			sony_nc_setup_rfkill(device, SONY_WIFI);
 
-		if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
+		if (dev_code == 0x10 && !snc_rfkill.devices[SONY_BLUETOOTH])
 			sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
 
-		if ((0xf0 & dev_code) == 0x20 &&
-				!sony_rfkill_devices[SONY_WWAN])
+		if (((0xf0 & dev_code) == 0x20 || (0xf0 & dev_code) == 0x50) &&
+				!snc_rfkill.devices[SONY_WWAN])
 			sony_nc_setup_rfkill(device, SONY_WWAN);
 
-		if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
+		if (dev_code == 0x30 && !snc_rfkill.devices[SONY_WIMAX])
 			sony_nc_setup_rfkill(device, SONY_WIMAX);
 	}
 
@@ -1717,7 +1735,7 @@ static int sony_nc_handles_setup(struct 
 			ret = sony_nc_kbd_backlight_setup(pd, handle);
 		case 0x0124:
 		case 0x0135:
-			ret = sony_nc_rfkill_setup(sony_nc_acpi_device);
+			ret = sony_nc_rfkill_setup(sony_nc_acpi_device, handle);
 			break;
 		default:
 			continue;
#27 lore raw

PATCH v2 13/14 sony-laptop: input core improvements

In reply to Marco Chiappero

Added a couple of Fn combos and sorted keys by "scancode" number. Fixed a small error in a comment too.

---

drivers/platform/x86/sony-laptop.c +9 -5
@@ -239,7 +239,7 @@ static int sony_laptop_input_index[] = {
 	57,	/* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
 	-1,	/* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
 	58,	/* 72 SONYPI_EVENT_MEDIA_PRESSED */
-	59,	/* 72 SONYPI_EVENT_VENDOR_PRESSED */
+	59,	/* 73 SONYPI_EVENT_VENDOR_PRESSED */
 };
 
 static int sony_laptop_input_keycode_map[] = {
@@ -1084,10 +1084,6 @@ struct sony_nc_event {
 };
 
 static struct sony_nc_event sony_100_events[] = {
-	{ 0x90, SONYPI_EVENT_PKEY_P1 },
-	{ 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
-	{ 0x91, SONYPI_EVENT_PKEY_P2 },
-	{ 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
 	{ 0x81, SONYPI_EVENT_FNKEY_F1 },
 	{ 0x01, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x82, SONYPI_EVENT_FNKEY_F2 },
@@ -1102,12 +1098,20 @@ static struct sony_nc_event sony_100_eve
 	{ 0x06, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x87, SONYPI_EVENT_FNKEY_F7 },
 	{ 0x07, SONYPI_EVENT_FNKEY_RELEASED },
+	{ 0x88, SONYPI_EVENT_FNKEY_F8 },
+	{ 0x08, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x89, SONYPI_EVENT_FNKEY_F9 },
 	{ 0x09, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x8A, SONYPI_EVENT_FNKEY_F10 },
 	{ 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
+	{ 0x8B, SONYPI_EVENT_FNKEY_F11 },
+	{ 0x0B, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x8C, SONYPI_EVENT_FNKEY_F12 },
 	{ 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
+	{ 0x90, SONYPI_EVENT_PKEY_P1 },
+	{ 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
+	{ 0x91, SONYPI_EVENT_PKEY_P2 },
+	{ 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
 	{ 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
 	{ 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
 	{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
#28 lore raw

PATCH RESEND v2 13/14 sony-laptop: input core improvements

In reply to Marco Chiappero

Added a couple of Fn combos and sorted keys by "scancode" number. Fixed a small error in a comment too.

---

drivers/platform/x86/sony-laptop.c +9 -5
@@ -239,7 +239,7 @@ static int sony_laptop_input_index[] = {
 	57,	/* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
 	-1,	/* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
 	58,	/* 72 SONYPI_EVENT_MEDIA_PRESSED */
-	59,	/* 72 SONYPI_EVENT_VENDOR_PRESSED */
+	59,	/* 73 SONYPI_EVENT_VENDOR_PRESSED */
 };
 
 static int sony_laptop_input_keycode_map[] = {
@@ -1084,10 +1084,6 @@ struct sony_nc_event {
 };
 
 static struct sony_nc_event sony_100_events[] = {
-	{ 0x90, SONYPI_EVENT_PKEY_P1 },
-	{ 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
-	{ 0x91, SONYPI_EVENT_PKEY_P2 },
-	{ 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
 	{ 0x81, SONYPI_EVENT_FNKEY_F1 },
 	{ 0x01, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x82, SONYPI_EVENT_FNKEY_F2 },
@@ -1102,12 +1098,20 @@ static struct sony_nc_event sony_100_eve
 	{ 0x06, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x87, SONYPI_EVENT_FNKEY_F7 },
 	{ 0x07, SONYPI_EVENT_FNKEY_RELEASED },
+	{ 0x88, SONYPI_EVENT_FNKEY_F8 },
+	{ 0x08, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x89, SONYPI_EVENT_FNKEY_F9 },
 	{ 0x09, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x8A, SONYPI_EVENT_FNKEY_F10 },
 	{ 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
+	{ 0x8B, SONYPI_EVENT_FNKEY_F11 },
+	{ 0x0B, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x8C, SONYPI_EVENT_FNKEY_F12 },
 	{ 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
+	{ 0x90, SONYPI_EVENT_PKEY_P1 },
+	{ 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
+	{ 0x91, SONYPI_EVENT_PKEY_P2 },
+	{ 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
 	{ 0x9d, SONYPI_EVENT_ZOOM_PRESSED },
 	{ 0x1d, SONYPI_EVENT_ANYBUTTON_RELEASED },
 	{ 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
#29 lore raw

PATCH v2 14/14 sony-laptop: Documentation changes

In reply to Marco Chiappero

Since new findings occurred and we have a better understanding of the SNC device, the development documentation is updated.

---

Documentation/laptops/sony-laptop.txt +2 -9
@@ -88,15 +88,36 @@ REPEAT: DON'T DO THIS IF YOU DON'T LIKE 
 In your kernel logs you will find the list of all ACPI methods
 the SNC device has on your laptop.
 
-* For new models you will see a long list of meaningless method names,
-reading the DSDT table source should reveal that:
-(1) the SNC device uses an internal capability lookup table
-(2) SN00 is used to find values in the lookup table
-(3) SN06 and SN07 are used to call into the real methods based on
-    offsets you can obtain iterating the table using SN00
-(4) SN02 used to enable events.
-Some values in the capability lookup table are more or less known, see
-the code for all sony_call_snc_handle calls, others are more obscure.
+* For new models you may see a long list of meaningless method names,
+but a small subset of methods starting with "SN" is always present.

These
+methods define a common interface for acting with the SNC device. In +particular:
+
+- SN00 can be used to retrieve some informations about the SNC device; among
+ them, an internal capability lookup table reporting model specific features,
+ identified by a number called "handle", associated to an offset, to be
+ later used by methods SN06 and SN07. Some handles are now well known, while
+ some others are still a bit obscure or totally unknown. A list of known
+ handles can be found at
http://www.absence.it/vaio-acpi/handles_list.txt
+
+- SN01, SN02, SN03 can be used to query, enable and disable (respectively)
+ the event generation for every handle, as they might trigger ACPI
+ notifications
+
+- SN04, SN05 can be used to query and clear the "event raised" flag for every
+ handle
+
+- SN06 and SN07 are used to call into the real methods, providing the handles
+ specific features, based on offsets you can obtain iterating the table
+ via SN00. They should provide the same info (or almost the same), but while
+ SN07 uses 32bit integers for both input and output parameters SN06 returns a
+ wide buffer (for both input and output values), useful for reading a few info
+ tables or long input parameters.
+
+You can have a look at a decoded, analyzed and fully explained DSDT taken from
+a Sony Vaio VPCS1 model at
http://www.absence.it/vaio-acpi/VPCS-findings.txt.
+It should significantly help you in understanding how to use handles/offsets,
+in decoding other DSDTs and in discovering new unknown features.

* For old models you can see the GCDP/GCDP methods used to pwer on/off the CD drive, but there are others and they are usually different from

#30 lore raw

PATCH RESEND v2 14/14 sony-laptop: documentation changes

In reply to Marco Chiappero

Since new findings occurred and we have a better understanding of the SNC device, the development documentation is updated.

---

Documentation/laptops/sony-laptop.txt +30 -9
@@ -88,15 +88,36 @@ REPEAT: DON'T DO THIS IF YOU DON'T LIKE 
 In your kernel logs you will find the list of all ACPI methods
 the SNC device has on your laptop.
 
-* For new models you will see a long list of meaningless method names,
-reading the DSDT table source should reveal that:
-(1) the SNC device uses an internal capability lookup table
-(2) SN00 is used to find values in the lookup table
-(3) SN06 and SN07 are used to call into the real methods based on
-    offsets you can obtain iterating the table using SN00
-(4) SN02 used to enable events.
-Some values in the capability lookup table are more or less known, see
-the code for all sony_call_snc_handle calls, others are more obscure.
+* For new models you may see a long list of meaningless method names,
+but a small subset of methods starting with "SN" is always present. These
+methods define a common interface for acting with the SNC device. In
+particular:
+
+- SN00 can be used to retrieve some informations about the SNC device; among
+  them, an internal capability lookup table reporting model specific features,
+  identified by a number called "handle", associated to an offset, to be
+  later used by methods SN06 and SN07. Some handles are now well known, while
+  some others are still a bit obscure or totally unknown. A list of known
+  handles can be found at http://www.absence.it/vaio-acpi/handles_list.txt
+
+- SN01, SN02, SN03 can be used to query, enable and disable (respectively)
+  the event generation for every handle, as they might trigger ACPI
+  notifications
+
+- SN04, SN05 can be used to query and clear the "event raised" flag for every
+  handle
+
+- SN06 and SN07 are used to call into the real methods, providing the handles
+  specific features, based on offsets you can obtain iterating the table
+  via SN00. They should provide the same info (or almost the same), but while
+  SN07 uses 32bit integers for both input and output parameters SN06 returns a
+  wide buffer (for both input and output values), useful for reading a few info
+  tables or long input parameters.
+
+You can have a look at a decoded, analyzed and fully explained DSDT taken from
+a Sony Vaio VPCS1 model at http://www.absence.it/vaio-acpi/VPCS-findings.txt.
+It should significantly help you in understanding how to use handles/offsets,
+in decoding other DSDTs and in discovering new unknown features.
 
 * For old models you can see the GCDP/GCDP methods used to pwer on/off
 the CD drive, but there are others and they are usually different from