Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[pandora-kernel.git] / drivers / platform / x86 / sony-laptop.c
index 13d8d63..8f709ae 100644 (file)
@@ -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;
 }
 
 /*
@@ -857,11 +950,39 @@ 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);
+
+       sony_call_snc_handle(*handle, 0x0200, &result);
+
+       return result & 0xff;
+}
+
+static int sony_nc_update_status_ng(struct backlight_device *bd)
+{
+       int value, result;
+       int *handle = (int *)bl_get_data(bd);
+
+       value = bd->props.brightness;
+       sony_call_snc_handle(*handle, 0x0100 | (value << 16), &result);
+
+       return sony_nc_get_brightness_ng(bd);
+}
+
 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,
+};
+static int backlight_ng_handle;
+static struct backlight_device *sony_backlight_device;
 
 /*
  * New SNC-only Vaios event mapping to driver known keys
@@ -972,7 +1093,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 +1117,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 +1158,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 +1175,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 +1325,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 +1364,237 @@ 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_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) {
+               backlight_ng_handle = 0x12f;
+               ops = &sony_backlight_ng_ops;
+               max_brightness = 0xff;
+
+       } else if (sony_find_snc_handle(0x137) != -1) {
+               backlight_ng_handle = 0x137;
+               ops = &sony_backlight_ng_ops;
+               max_brightness = 0xff;
+
+       } 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_backlight_device = backlight_device_register("sony", NULL,
+                                                         &backlight_ng_handle,
+                                                         ops, &props);
+
+       if (IS_ERR(sony_backlight_device)) {
+               pr_warning(DRV_PFX "unable to register backlight device\n");
+               sony_backlight_device = NULL;
+       } else
+               sony_backlight_device->props.brightness =
+                   ops->get_brightness(sony_backlight_device);
+}
+
+static void sony_nc_backlight_cleanup(void)
+{
+       if (sony_backlight_device)
+               backlight_device_unregister(sony_backlight_device);
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
        acpi_status status;
@@ -1252,8 +1602,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 +1619,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 +1643,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,40 +1656,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.type = BACKLIGHT_PLATFORM;
-               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) {
 
@@ -1374,14 +1712,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;
@@ -1391,8 +1734,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;
 
@@ -1400,6 +1742,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();
@@ -1438,7 +1782,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
@@ -1584,8 +1927,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 }
 };
 
@@ -1842,7 +2185,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);
 }
@@ -1890,7 +2233,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;
        }
 
@@ -1910,7 +2253,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;
        }
 
@@ -1933,7 +2276,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;
        }
 
@@ -1989,7 +2332,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;
        }
@@ -2396,7 +2739,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;
        }
 
@@ -2406,11 +2749,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;
@@ -2470,8 +2813,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;
                                }
@@ -2510,7 +2852,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;
@@ -2538,7 +2880,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;
        }
 
@@ -2554,8 +2896,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;
        }
@@ -2669,7 +3010,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;
        }
@@ -2725,6 +3066,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;
                        }
                }
@@ -2744,7 +3088,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;
 }
 
@@ -2759,7 +3102,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;
        }
 
@@ -2799,8 +3142,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");
@@ -2810,16 +3153,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;
        }
 
@@ -2829,7 +3170,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);
@@ -2837,7 +3178,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);
@@ -2860,7 +3201,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;
        }
@@ -2880,7 +3221,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;
        }
@@ -2888,7 +3229,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;
        }
 
@@ -2997,8 +3338,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;
@@ -3006,7 +3346,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;
        }