diff options
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 629 |
1 files changed, 525 insertions, 104 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5e83370b0812..6fe8cd6e23b5 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -71,8 +71,9 @@ #endif #define DRV_PFX "sony-laptop: " -#define dprintk(msg...) do { \ - if (debug) printk(KERN_WARNING DRV_PFX msg); \ +#define dprintk(msg...) do { \ + if (debug) \ + pr_warn(DRV_PFX msg); \ } while (0) #define SONY_LAPTOP_DRIVER_VERSION "0.6" @@ -124,6 +125,21 @@ MODULE_PARM_DESC(minor, "default is -1 (automatic)"); #endif +static int kbd_backlight; /* = 1 */ +module_param(kbd_backlight, int, 0444); +MODULE_PARM_DESC(kbd_backlight, + "set this to 0 to disable keyboard backlight, " + "1 to enable it (default: 0)"); + +static int kbd_backlight_timeout; /* = 0 */ +module_param(kbd_backlight_timeout, int, 0444); +MODULE_PARM_DESC(kbd_backlight_timeout, + "set this to 0 to set the default 10 seconds 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, SONY_BLUETOOTH, @@ -402,7 +418,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) error = kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); if (error) { - printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); + pr_err(DRV_PFX "kfifo_alloc failed\n"); goto err_dec_users; } @@ -591,7 +607,7 @@ struct sony_nc_value { int value; /* current setting */ int valid; /* Has ever been set */ int debug; /* active only in debug mode ? */ - struct device_attribute devattr; /* sysfs atribute */ + struct device_attribute devattr; /* sysfs attribute */ }; #define SNC_HANDLE_NAMES(_name, _values...) \ @@ -686,7 +702,7 @@ static int acpi_callgetfunc(acpi_handle handle, char *name, int *result) return 0; } - printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n"); + pr_warn(DRV_PFX "acpi_callreadfunc failed\n"); return -1; } @@ -712,7 +728,7 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, if (status == AE_OK) { if (result != NULL) { if (out_obj.type != ACPI_TYPE_INTEGER) { - printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad " + pr_warn(DRV_PFX "acpi_evaluate_object bad " "return type\n"); return -1; } @@ -721,34 +737,111 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, return 0; } - printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n"); + pr_warn(DRV_PFX "acpi_evaluate_object failed\n"); return -1; } -static int sony_find_snc_handle(int handle) +struct sony_nc_handles { + u16 cap[0x10]; + struct device_attribute devattr; +}; + +static struct sony_nc_handles *handles; + +static ssize_t sony_nc_handles_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { + len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ", + handles->cap[i]); + } + len += snprintf(buffer + len, PAGE_SIZE - len, "\n"); + + return len; +} + +static int sony_nc_handles_setup(struct platform_device *pd) { int i; int result; - for (i = 0x20; i < 0x30; i++) { - acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); - if (result == handle) - return i-0x20; + handles = kzalloc(sizeof(*handles), GFP_KERNEL); + if (!handles) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { + if (!acpi_callsetfunc(sony_nc_acpi_handle, + "SN00", i + 0x20, &result)) { + dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n", + result, i); + handles->cap[i] = result; + } + } + + if (debug) { + sysfs_attr_init(&handles->devattr.attr); + handles->devattr.attr.name = "handles"; + handles->devattr.attr.mode = S_IRUGO; + handles->devattr.show = sony_nc_handles_show; + + /* allow reading capabilities via sysfs */ + if (device_create_file(&pd->dev, &handles->devattr)) { + kfree(handles); + handles = NULL; + return -1; + } } + return 0; +} + +static int sony_nc_handles_cleanup(struct platform_device *pd) +{ + if (handles) { + if (debug) + device_remove_file(&pd->dev, &handles->devattr); + kfree(handles); + handles = NULL; + } + return 0; +} + +static int sony_find_snc_handle(int handle) +{ + int i; + + /* not initialized yet, return early */ + if (!handles) + return -1; + + for (i = 0; i < 0x10; i++) { + if (handles->cap[i] == handle) { + dprintk("found handle 0x%.4x (offset: 0x%.2x)\n", + handle, i); + return i; + } + } + dprintk("handle 0x%.4x not found\n", handle); return -1; } static int sony_call_snc_handle(int handle, int argument, int *result) { + int ret = 0; int offset = sony_find_snc_handle(handle); if (offset < 0) return -1; - return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, - result); + ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, + result); + dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument, + *result); + return ret; } /* @@ -841,6 +934,14 @@ static ssize_t sony_nc_sysfs_store(struct device *dev, /* * Backlight device */ +struct sony_backlight_props { + struct backlight_device *dev; + int handle; + u8 offset; + u8 maxlvl; +}; +struct sony_backlight_props sony_bl_props; + static int sony_backlight_update_status(struct backlight_device *bd) { return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT", @@ -857,11 +958,42 @@ static int sony_backlight_get_brightness(struct backlight_device *bd) return value - 1; } -static struct backlight_device *sony_backlight_device; +static int sony_nc_get_brightness_ng(struct backlight_device *bd) +{ + int result; + int *handle = (int *)bl_get_data(bd); + struct sony_backlight_props *sdev = + (struct sony_backlight_props *)bl_get_data(bd); + + sony_call_snc_handle(sdev->handle, 0x0200, &result); + + return (result & 0xff) - sdev->offset; +} + +static int sony_nc_update_status_ng(struct backlight_device *bd) +{ + int value, result; + int *handle = (int *)bl_get_data(bd); + struct sony_backlight_props *sdev = + (struct sony_backlight_props *)bl_get_data(bd); + + value = bd->props.brightness + sdev->offset; + if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result)) + return -EIO; + + return value; +} + static const struct backlight_ops sony_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, .update_status = sony_backlight_update_status, .get_brightness = sony_backlight_get_brightness, }; +static const struct backlight_ops sony_backlight_ng_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = sony_nc_update_status_ng, + .get_brightness = sony_nc_get_brightness_ng, +}; /* * New SNC-only Vaios event mapping to driver known keys @@ -972,7 +1104,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) } if (!key_event->data) - printk(KERN_INFO DRV_PFX + pr_info(DRV_PFX "Unknown event: 0x%x 0x%x\n", key_handle, ev); @@ -996,7 +1128,7 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, struct acpi_device_info *info; if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { - printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", + pr_warn(DRV_PFX "method: name: %4.4s, args %X\n", (char *)&info->name, info->param_count); kfree(info); @@ -1037,7 +1169,7 @@ static int sony_nc_resume(struct acpi_device *device) ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset, item->value, NULL); if (ret < 0) { - printk("%s: %d\n", __func__, ret); + pr_err(DRV_PFX "%s: %d\n", __func__, ret); break; } } @@ -1054,14 +1186,12 @@ static int sony_nc_resume(struct acpi_device *device) sony_nc_function_setup(device); } - /* set the last requested brightness level */ - if (sony_backlight_device && - sony_backlight_update_status(sony_backlight_device) < 0) - printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); - /* re-read rfkill state */ sony_nc_rfkill_update(); + /* restore kbd backlight states */ + sony_nc_kbd_backlight_resume(); + return 0; } @@ -1206,12 +1336,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) device_enum = (union acpi_object *) buffer.pointer; if (!device_enum) { - pr_err("Invalid SN06 return object\n"); + pr_err(DRV_PFX "No SN06 return object."); goto out_no_enum; } if (device_enum->type != ACPI_TYPE_BUFFER) { - pr_err("Invalid SN06 return object type 0x%.2x\n", - device_enum->type); + pr_err(DRV_PFX "Invalid SN06 return object 0x%.2x\n", + device_enum->type); goto out_no_enum; } @@ -1245,6 +1375,306 @@ out_no_enum: return; } +/* 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; + struct device_attribute mode_attr; + struct device_attribute timeout_attr; +}; + +static struct kbd_backlight *kbdbl_handle; + +static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) +{ + int result; + + if (value > 1) + return -EINVAL; + + if (sony_call_snc_handle(KBDBL_HANDLER, + (value << 0x10) | SET_MODE, &result)) + return -EIO; + + /* Try to turn the light on/off immediately */ + sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE, + &result); + + kbdbl_handle->mode = value; + + return 0; +} + +static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buffer, size_t count) +{ + int ret = 0; + unsigned long value; + + if (count > 31) + return -EINVAL; + + if (strict_strtoul(buffer, 10, &value)) + return -EINVAL; + + ret = __sony_nc_kbd_backlight_mode_set(value); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + ssize_t count = 0; + count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode); + return count; +} + +static int __sony_nc_kbd_backlight_timeout_set(u8 value) +{ + int result; + + if (value > 3) + return -EINVAL; + + if (sony_call_snc_handle(KBDBL_HANDLER, + (value << 0x10) | SET_TIMEOUT, &result)) + return -EIO; + + kbdbl_handle->timeout = value; + + return 0; +} + +static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev, + struct device_attribute *attr, + const char *buffer, size_t count) +{ + int ret = 0; + unsigned long value; + + if (count > 31) + return -EINVAL; + + if (strict_strtoul(buffer, 10, &value)) + return -EINVAL; + + ret = __sony_nc_kbd_backlight_timeout_set(value); + if (ret < 0) + return ret; + + return count; +} + +static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev, + struct device_attribute *attr, char *buffer) +{ + ssize_t count = 0; + count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout); + return count; +} + +static int sony_nc_kbd_backlight_setup(struct platform_device *pd) +{ + int result; + + if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result)) + return 0; + if (!(result & 0x02)) + return 0; + + kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL); + if (!kbdbl_handle) + 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; + + if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr)) + goto outkzalloc; + + if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr)) + goto outmode; + + __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); +outkzalloc: + kfree(kbdbl_handle); + kbdbl_handle = NULL; + return -1; +} + +static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) +{ + if (kbdbl_handle) { + int result; + + device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); + device_remove_file(&pd->dev, &kbdbl_handle->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); + + kfree(kbdbl_handle); + } + return 0; +} + +static void sony_nc_kbd_backlight_resume(void) +{ + int ignore = 0; + + if (!kbdbl_handle) + 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); +} + +static void sony_nc_backlight_ng_read_limits(int handle, + struct sony_backlight_props *props) +{ + int offset; + acpi_status status; + u8 brlvl, i; + u8 min = 0xff, max = 0x00; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *lvl_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + + props->handle = handle; + props->offset = 0; + props->maxlvl = 0xff; + + offset = sony_find_snc_handle(handle); + if (offset < 0) + return; + + /* try to read the boundaries from ACPI tables, if we fail the above + * defaults should be reasonable + */ + 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", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) + return; + + lvl_enum = (union acpi_object *) buffer.pointer; + if (!lvl_enum) { + pr_err("No SN06 return object."); + return; + } + if (lvl_enum->type != ACPI_TYPE_BUFFER) { + pr_err("Invalid SN06 return object 0x%.2x\n", + lvl_enum->type); + goto out_invalid; + } + + /* the buffer lists brightness levels available, brightness levels are + * from 0 to 8 in the array, other values are used by ALS control. + */ + for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) { + + brlvl = *(lvl_enum->buffer.pointer + i); + dprintk("Brightness level: %d\n", brlvl); + + if (!brlvl) + break; + + if (brlvl > max) + max = brlvl; + if (brlvl < min) + min = brlvl; + } + props->offset = min; + props->maxlvl = max; + dprintk("Brightness levels: min=%d max=%d\n", props->offset, + props->maxlvl); + +out_invalid: + kfree(buffer.pointer); + return; +} + +static void sony_nc_backlight_setup(void) +{ + acpi_handle unused; + int max_brightness = 0; + const struct backlight_ops *ops = NULL; + struct backlight_properties props; + + if (sony_find_snc_handle(0x12f) != -1) { + ops = &sony_backlight_ng_ops; + sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props); + max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + + } else if (sony_find_snc_handle(0x137) != -1) { + ops = &sony_backlight_ng_ops; + sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props); + max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + + } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", + &unused))) { + ops = &sony_backlight_ops; + max_brightness = SONY_MAX_BRIGHTNESS - 1; + + } else + return; + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; + props.max_brightness = max_brightness; + sony_bl_props.dev = backlight_device_register("sony", NULL, + &sony_bl_props, + ops, &props); + + if (IS_ERR(sony_bl_props.dev)) { + pr_warn(DRV_PFX "unable to register backlight device\n"); + sony_bl_props.dev = NULL; + } else + sony_bl_props.dev->props.brightness = + ops->get_brightness(sony_bl_props.dev); +} + +static void sony_nc_backlight_cleanup(void) +{ + if (sony_bl_props.dev) + backlight_device_unregister(sony_bl_props.dev); +} + static int sony_nc_add(struct acpi_device *device) { acpi_status status; @@ -1252,8 +1682,8 @@ static int sony_nc_add(struct acpi_device *device) acpi_handle handle; struct sony_nc_value *item; - printk(KERN_INFO DRV_PFX "%s v%s.\n", - SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); + pr_info(DRV_PFX "%s v%s.\n", SONY_NC_DRIVER_NAME, + SONY_LAPTOP_DRIVER_VERSION); sony_nc_acpi_device = device; strcpy(acpi_device_class(device), "sony/hotkey"); @@ -1269,13 +1699,18 @@ static int sony_nc_add(struct acpi_device *device) goto outwalk; } + result = sony_pf_add(); + if (result) + goto outpresent; + if (debug) { - status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, - 1, sony_walk_callback, NULL, NULL, NULL); + status = acpi_walk_namespace(ACPI_TYPE_METHOD, + sony_nc_acpi_handle, 1, sony_walk_callback, + NULL, NULL, NULL); if (ACPI_FAILURE(status)) { - printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); + pr_warn(DRV_PFX "unable to walk acpi resources\n"); result = -ENODEV; - goto outwalk; + goto outpresent; } } @@ -1288,6 +1723,12 @@ static int sony_nc_add(struct acpi_device *device) if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); + 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); } @@ -1295,39 +1736,17 @@ static int sony_nc_add(struct acpi_device *device) /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); if (result) { - printk(KERN_ERR DRV_PFX - "Unable to create input devices.\n"); - goto outwalk; + pr_err(DRV_PFX "Unable to create input devices.\n"); + goto outkbdbacklight; } if (acpi_video_backlight_support()) { - printk(KERN_INFO DRV_PFX "brightness ignored, must be " + pr_info(DRV_PFX "brightness ignored, must be " "controlled by ACPI video driver\n"); - } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", - &handle))) { - struct backlight_properties props; - memset(&props, 0, sizeof(struct backlight_properties)); - props.max_brightness = SONY_MAX_BRIGHTNESS - 1; - sony_backlight_device = backlight_device_register("sony", NULL, - NULL, - &sony_backlight_ops, - &props); - - if (IS_ERR(sony_backlight_device)) { - printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); - sony_backlight_device = NULL; - } else { - sony_backlight_device->props.brightness = - sony_backlight_get_brightness - (sony_backlight_device); - } - + } else { + sony_nc_backlight_setup(); } - result = sony_pf_add(); - if (result) - goto outbacklight; - /* create sony_pf sysfs attributes related to the SNC device */ for (item = sony_nc_values; item->name; ++item) { @@ -1373,14 +1792,19 @@ static int sony_nc_add(struct acpi_device *device) for (item = sony_nc_values; item->name; ++item) { device_remove_file(&sony_pf_device->dev, &item->devattr); } - sony_pf_remove(); - - outbacklight: - if (sony_backlight_device) - backlight_device_unregister(sony_backlight_device); + sony_nc_backlight_cleanup(); sony_laptop_remove_input(); + outkbdbacklight: + sony_nc_kbd_backlight_cleanup(sony_pf_device); + + outsnc: + sony_nc_handles_cleanup(sony_pf_device); + + outpresent: + sony_pf_remove(); + outwalk: sony_nc_rfkill_cleanup(); return result; @@ -1390,8 +1814,7 @@ static int sony_nc_remove(struct acpi_device *device, int type) { struct sony_nc_value *item; - if (sony_backlight_device) - backlight_device_unregister(sony_backlight_device); + sony_nc_backlight_cleanup(); sony_nc_acpi_device = NULL; @@ -1399,6 +1822,8 @@ static int sony_nc_remove(struct acpi_device *device, int type) 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(); @@ -1437,7 +1862,6 @@ static struct acpi_driver sony_nc_driver = { #define SONYPI_DEVICE_TYPE1 0x00000001 #define SONYPI_DEVICE_TYPE2 0x00000002 #define SONYPI_DEVICE_TYPE3 0x00000004 -#define SONYPI_DEVICE_TYPE4 0x00000008 #define SONYPI_TYPE1_OFFSET 0x04 #define SONYPI_TYPE2_OFFSET 0x12 @@ -1583,8 +2007,8 @@ static struct sonypi_event sonypi_blueev[] = { /* The set of possible wireless events */ static struct sonypi_event sonypi_wlessev[] = { - { 0x59, SONYPI_EVENT_WIRELESS_ON }, - { 0x5a, SONYPI_EVENT_WIRELESS_OFF }, + { 0x59, SONYPI_EVENT_IGNORE }, + { 0x5a, SONYPI_EVENT_IGNORE }, { 0, 0 } }; @@ -1841,7 +2265,7 @@ out: if (pcidev) pci_dev_put(pcidev); - printk(KERN_INFO DRV_PFX "detected Type%d model\n", + pr_info(DRV_PFX "detected Type%d model\n", dev->model == SONYPI_DEVICE_TYPE1 ? 1 : dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); } @@ -1889,7 +2313,7 @@ static int __sony_pic_camera_ready(void) static int __sony_pic_camera_off(void) { if (!camera) { - printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); + pr_warn(DRV_PFX "camera control not enabled\n"); return -ENODEV; } @@ -1909,7 +2333,7 @@ static int __sony_pic_camera_on(void) int i, j, x; if (!camera) { - printk(KERN_WARNING DRV_PFX "camera control not enabled\n"); + pr_warn(DRV_PFX "camera control not enabled\n"); return -ENODEV; } @@ -1932,7 +2356,7 @@ static int __sony_pic_camera_on(void) } if (j == 0) { - printk(KERN_WARNING DRV_PFX "failed to power on camera\n"); + pr_warn(DRV_PFX "failed to power on camera\n"); return -ENODEV; } @@ -1988,7 +2412,7 @@ int sony_pic_camera_command(int command, u8 value) ITERATIONS_SHORT); break; default: - printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n", + pr_err(DRV_PFX "sony_pic_camera_command invalid: %d\n", command); break; } @@ -2246,7 +2670,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, mutex_lock(&spic_dev.lock); switch (cmd) { case SONYPI_IOCGBRT: - if (sony_backlight_device == NULL) { + if (sony_bl_props.dev == NULL) { ret = -EIO; break; } @@ -2259,7 +2683,7 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, ret = -EFAULT; break; case SONYPI_IOCSBRT: - if (sony_backlight_device == NULL) { + if (sony_bl_props.dev == NULL) { ret = -EIO; break; } @@ -2273,8 +2697,8 @@ static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, break; } /* sync the backlight device status */ - sony_backlight_device->props.brightness = - sony_backlight_get_brightness(sony_backlight_device); + sony_bl_props.dev->props.brightness = + sony_backlight_get_brightness(sony_bl_props.dev); break; case SONYPI_IOCGBAT1CAP: if (ec_read16(SONYPI_BAT1_FULL, &val16)) { @@ -2395,7 +2819,7 @@ static int sonypi_compat_init(void) error = kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); if (error) { - printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); + pr_err(DRV_PFX "kfifo_alloc failed\n"); return error; } @@ -2405,11 +2829,11 @@ static int sonypi_compat_init(void) sonypi_misc_device.minor = minor; error = misc_register(&sonypi_misc_device); if (error) { - printk(KERN_ERR DRV_PFX "misc_register failed\n"); + pr_err(DRV_PFX "misc_register failed\n"); goto err_free_kfifo; } if (minor == -1) - printk(KERN_INFO DRV_PFX "device allocated minor is %d\n", + pr_info(DRV_PFX "device allocated minor is %d\n", sonypi_misc_device.minor); return 0; @@ -2469,8 +2893,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) } for (i = 0; i < p->interrupt_count; i++) { if (!p->interrupts[i]) { - printk(KERN_WARNING DRV_PFX - "Invalid IRQ %d\n", + pr_warn(DRV_PFX "Invalid IRQ %d\n", p->interrupts[i]); continue; } @@ -2509,7 +2932,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context) ioport->io2.address_length); } else { - printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n"); + pr_err(DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n"); return AE_ERROR; } return AE_OK; @@ -2537,7 +2960,7 @@ static int sony_pic_possible_resources(struct acpi_device *device) dprintk("Evaluating _STA\n"); result = acpi_bus_get_status(device); if (result) { - printk(KERN_WARNING DRV_PFX "Unable to read status\n"); + pr_warn(DRV_PFX "Unable to read status\n"); goto end; } @@ -2553,8 +2976,7 @@ static int sony_pic_possible_resources(struct acpi_device *device) status = acpi_walk_resources(device->handle, METHOD_NAME__PRS, sony_pic_read_possible_resource, &spic_dev); if (ACPI_FAILURE(status)) { - printk(KERN_WARNING DRV_PFX - "Failure evaluating %s\n", + pr_warn(DRV_PFX "Failure evaluating %s\n", METHOD_NAME__PRS); result = -ENODEV; } @@ -2668,7 +3090,7 @@ static int sony_pic_enable(struct acpi_device *device, /* check for total failure */ if (ACPI_FAILURE(status)) { - printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n"); + pr_err(DRV_PFX "Error evaluating _SRS\n"); result = -ENODEV; goto end; } @@ -2724,6 +3146,9 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id) if (ev == dev->event_types[i].events[j].data) { device_event = dev->event_types[i].events[j].event; + /* some events may require ignoring */ + if (!device_event) + return IRQ_HANDLED; goto found; } } @@ -2743,7 +3168,6 @@ found: sony_laptop_report_input_event(device_event); acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); sonypi_compat_report_event(device_event); - return IRQ_HANDLED; } @@ -2758,7 +3182,7 @@ static int sony_pic_remove(struct acpi_device *device, int type) struct sony_pic_irq *irq, *tmp_irq; if (sony_pic_disable(device)) { - printk(KERN_ERR DRV_PFX "Couldn't disable device.\n"); + pr_err(DRV_PFX "Couldn't disable device.\n"); return -ENXIO; } @@ -2798,8 +3222,8 @@ static int sony_pic_add(struct acpi_device *device) struct sony_pic_ioport *io, *tmp_io; struct sony_pic_irq *irq, *tmp_irq; - printk(KERN_INFO DRV_PFX "%s v%s.\n", - SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION); + pr_info(DRV_PFX "%s v%s.\n", SONY_PIC_DRIVER_NAME, + SONY_LAPTOP_DRIVER_VERSION); spic_dev.acpi_dev = device; strcpy(acpi_device_class(device), "sony/hotkey"); @@ -2809,16 +3233,14 @@ static int sony_pic_add(struct acpi_device *device) /* read _PRS resources */ result = sony_pic_possible_resources(device); if (result) { - printk(KERN_ERR DRV_PFX - "Unable to read possible resources.\n"); + pr_err(DRV_PFX "Unable to read possible resources.\n"); goto err_free_resources; } /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); if (result) { - printk(KERN_ERR DRV_PFX - "Unable to create input devices.\n"); + pr_err(DRV_PFX "Unable to create input devices.\n"); goto err_free_resources; } @@ -2828,7 +3250,7 @@ static int sony_pic_add(struct acpi_device *device) /* request io port */ list_for_each_entry_reverse(io, &spic_dev.ioports, list) { if (request_region(io->io1.minimum, io->io1.address_length, - "Sony Programable I/O Device")) { + "Sony Programmable I/O Device")) { dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n", io->io1.minimum, io->io1.maximum, io->io1.address_length); @@ -2836,7 +3258,7 @@ static int sony_pic_add(struct acpi_device *device) if (io->io2.minimum) { if (request_region(io->io2.minimum, io->io2.address_length, - "Sony Programable I/O Device")) { + "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); @@ -2859,7 +3281,7 @@ static int sony_pic_add(struct acpi_device *device) } } if (!spic_dev.cur_ioport) { - printk(KERN_ERR DRV_PFX "Failed to request_region.\n"); + pr_err(DRV_PFX "Failed to request_region.\n"); result = -ENODEV; goto err_remove_compat; } @@ -2879,7 +3301,7 @@ static int sony_pic_add(struct acpi_device *device) } } if (!spic_dev.cur_irq) { - printk(KERN_ERR DRV_PFX "Failed to request_irq.\n"); + pr_err(DRV_PFX "Failed to request_irq.\n"); result = -ENODEV; goto err_release_region; } @@ -2887,7 +3309,7 @@ static int sony_pic_add(struct acpi_device *device) /* set resource status _SRS */ result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq); if (result) { - printk(KERN_ERR DRV_PFX "Couldn't enable device.\n"); + pr_err(DRV_PFX "Couldn't enable device.\n"); goto err_free_irq; } @@ -2996,8 +3418,7 @@ static int __init sony_laptop_init(void) if (!no_spic && dmi_check_system(sonypi_dmi_table)) { result = acpi_bus_register_driver(&sony_pic_driver); if (result) { - printk(KERN_ERR DRV_PFX - "Unable to register SPIC driver."); + pr_err(DRV_PFX "Unable to register SPIC driver."); goto out; } spic_drv_registered = 1; @@ -3005,7 +3426,7 @@ static int __init sony_laptop_init(void) result = acpi_bus_register_driver(&sony_nc_driver); if (result) { - printk(KERN_ERR DRV_PFX "Unable to register SNC driver."); + pr_err(DRV_PFX "Unable to register SNC driver."); goto out_unregister_pic; } |