diff options
Diffstat (limited to 'drivers/platform/x86/ideapad-laptop.c')
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 251 |
1 files changed, 217 insertions, 34 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 0c595410e788..a36addf106a0 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/input/sparse-keymap.h> | 34 | #include <linux/input/sparse-keymap.h> |
35 | #include <linux/backlight.h> | 35 | #include <linux/backlight.h> |
36 | #include <linux/fb.h> | 36 | #include <linux/fb.h> |
37 | #include <linux/debugfs.h> | ||
38 | #include <linux/seq_file.h> | ||
37 | 39 | ||
38 | #define IDEAPAD_RFKILL_DEV_NUM (3) | 40 | #define IDEAPAD_RFKILL_DEV_NUM (3) |
39 | 41 | ||
@@ -42,15 +44,41 @@ | |||
42 | #define CFG_WIFI_BIT (18) | 44 | #define CFG_WIFI_BIT (18) |
43 | #define CFG_CAMERA_BIT (19) | 45 | #define CFG_CAMERA_BIT (19) |
44 | 46 | ||
47 | enum { | ||
48 | VPCCMD_R_VPC1 = 0x10, | ||
49 | VPCCMD_R_BL_MAX, | ||
50 | VPCCMD_R_BL, | ||
51 | VPCCMD_W_BL, | ||
52 | VPCCMD_R_WIFI, | ||
53 | VPCCMD_W_WIFI, | ||
54 | VPCCMD_R_BT, | ||
55 | VPCCMD_W_BT, | ||
56 | VPCCMD_R_BL_POWER, | ||
57 | VPCCMD_R_NOVO, | ||
58 | VPCCMD_R_VPC2, | ||
59 | VPCCMD_R_TOUCHPAD, | ||
60 | VPCCMD_W_TOUCHPAD, | ||
61 | VPCCMD_R_CAMERA, | ||
62 | VPCCMD_W_CAMERA, | ||
63 | VPCCMD_R_3G, | ||
64 | VPCCMD_W_3G, | ||
65 | VPCCMD_R_ODD, /* 0x21 */ | ||
66 | VPCCMD_R_RF = 0x23, | ||
67 | VPCCMD_W_RF, | ||
68 | VPCCMD_W_BL_POWER = 0x33, | ||
69 | }; | ||
70 | |||
45 | struct ideapad_private { | 71 | struct ideapad_private { |
46 | struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; | 72 | struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM]; |
47 | struct platform_device *platform_device; | 73 | struct platform_device *platform_device; |
48 | struct input_dev *inputdev; | 74 | struct input_dev *inputdev; |
49 | struct backlight_device *blightdev; | 75 | struct backlight_device *blightdev; |
76 | struct dentry *debug; | ||
50 | unsigned long cfg; | 77 | unsigned long cfg; |
51 | }; | 78 | }; |
52 | 79 | ||
53 | static acpi_handle ideapad_handle; | 80 | static acpi_handle ideapad_handle; |
81 | static struct ideapad_private *ideapad_priv; | ||
54 | static bool no_bt_rfkill; | 82 | static bool no_bt_rfkill; |
55 | module_param(no_bt_rfkill, bool, 0444); | 83 | module_param(no_bt_rfkill, bool, 0444); |
56 | MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); | 84 | MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); |
@@ -164,6 +192,146 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data) | |||
164 | } | 192 | } |
165 | 193 | ||
166 | /* | 194 | /* |
195 | * debugfs | ||
196 | */ | ||
197 | #define DEBUGFS_EVENT_LEN (4096) | ||
198 | static int debugfs_status_show(struct seq_file *s, void *data) | ||
199 | { | ||
200 | unsigned long value; | ||
201 | |||
202 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value)) | ||
203 | seq_printf(s, "Backlight max:\t%lu\n", value); | ||
204 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value)) | ||
205 | seq_printf(s, "Backlight now:\t%lu\n", value); | ||
206 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value)) | ||
207 | seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off"); | ||
208 | seq_printf(s, "=====================\n"); | ||
209 | |||
210 | if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value)) | ||
211 | seq_printf(s, "Radio status:\t%s(%lu)\n", | ||
212 | value ? "On" : "Off", value); | ||
213 | if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value)) | ||
214 | seq_printf(s, "Wifi status:\t%s(%lu)\n", | ||
215 | value ? "On" : "Off", value); | ||
216 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value)) | ||
217 | seq_printf(s, "BT status:\t%s(%lu)\n", | ||
218 | value ? "On" : "Off", value); | ||
219 | if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value)) | ||
220 | seq_printf(s, "3G status:\t%s(%lu)\n", | ||
221 | value ? "On" : "Off", value); | ||
222 | seq_printf(s, "=====================\n"); | ||
223 | |||
224 | if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value)) | ||
225 | seq_printf(s, "Touchpad status:%s(%lu)\n", | ||
226 | value ? "On" : "Off", value); | ||
227 | if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value)) | ||
228 | seq_printf(s, "Camera status:\t%s(%lu)\n", | ||
229 | value ? "On" : "Off", value); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int debugfs_status_open(struct inode *inode, struct file *file) | ||
235 | { | ||
236 | return single_open(file, debugfs_status_show, NULL); | ||
237 | } | ||
238 | |||
239 | static const struct file_operations debugfs_status_fops = { | ||
240 | .owner = THIS_MODULE, | ||
241 | .open = debugfs_status_open, | ||
242 | .read = seq_read, | ||
243 | .llseek = seq_lseek, | ||
244 | .release = single_release, | ||
245 | }; | ||
246 | |||
247 | static int debugfs_cfg_show(struct seq_file *s, void *data) | ||
248 | { | ||
249 | if (!ideapad_priv) { | ||
250 | seq_printf(s, "cfg: N/A\n"); | ||
251 | } else { | ||
252 | seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ", | ||
253 | ideapad_priv->cfg); | ||
254 | if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg)) | ||
255 | seq_printf(s, "Bluetooth "); | ||
256 | if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg)) | ||
257 | seq_printf(s, "3G "); | ||
258 | if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg)) | ||
259 | seq_printf(s, "Wireless "); | ||
260 | if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg)) | ||
261 | seq_printf(s, "Camera "); | ||
262 | seq_printf(s, "\nGraphic: "); | ||
263 | switch ((ideapad_priv->cfg)&0x700) { | ||
264 | case 0x100: | ||
265 | seq_printf(s, "Intel"); | ||
266 | break; | ||
267 | case 0x200: | ||
268 | seq_printf(s, "ATI"); | ||
269 | break; | ||
270 | case 0x300: | ||
271 | seq_printf(s, "Nvidia"); | ||
272 | break; | ||
273 | case 0x400: | ||
274 | seq_printf(s, "Intel and ATI"); | ||
275 | break; | ||
276 | case 0x500: | ||
277 | seq_printf(s, "Intel and Nvidia"); | ||
278 | break; | ||
279 | } | ||
280 | seq_printf(s, "\n"); | ||
281 | } | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int debugfs_cfg_open(struct inode *inode, struct file *file) | ||
286 | { | ||
287 | return single_open(file, debugfs_cfg_show, NULL); | ||
288 | } | ||
289 | |||
290 | static const struct file_operations debugfs_cfg_fops = { | ||
291 | .owner = THIS_MODULE, | ||
292 | .open = debugfs_cfg_open, | ||
293 | .read = seq_read, | ||
294 | .llseek = seq_lseek, | ||
295 | .release = single_release, | ||
296 | }; | ||
297 | |||
298 | static int __devinit ideapad_debugfs_init(struct ideapad_private *priv) | ||
299 | { | ||
300 | struct dentry *node; | ||
301 | |||
302 | priv->debug = debugfs_create_dir("ideapad", NULL); | ||
303 | if (priv->debug == NULL) { | ||
304 | pr_err("failed to create debugfs directory"); | ||
305 | goto errout; | ||
306 | } | ||
307 | |||
308 | node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL, | ||
309 | &debugfs_cfg_fops); | ||
310 | if (!node) { | ||
311 | pr_err("failed to create cfg in debugfs"); | ||
312 | goto errout; | ||
313 | } | ||
314 | |||
315 | node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL, | ||
316 | &debugfs_status_fops); | ||
317 | if (!node) { | ||
318 | pr_err("failed to create event in debugfs"); | ||
319 | goto errout; | ||
320 | } | ||
321 | |||
322 | return 0; | ||
323 | |||
324 | errout: | ||
325 | return -ENOMEM; | ||
326 | } | ||
327 | |||
328 | static void ideapad_debugfs_exit(struct ideapad_private *priv) | ||
329 | { | ||
330 | debugfs_remove_recursive(priv->debug); | ||
331 | priv->debug = NULL; | ||
332 | } | ||
333 | |||
334 | /* | ||
167 | * sysfs | 335 | * sysfs |
168 | */ | 336 | */ |
169 | static ssize_t show_ideapad_cam(struct device *dev, | 337 | static ssize_t show_ideapad_cam(struct device *dev, |
@@ -172,7 +340,7 @@ static ssize_t show_ideapad_cam(struct device *dev, | |||
172 | { | 340 | { |
173 | unsigned long result; | 341 | unsigned long result; |
174 | 342 | ||
175 | if (read_ec_data(ideapad_handle, 0x1D, &result)) | 343 | if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result)) |
176 | return sprintf(buf, "-1\n"); | 344 | return sprintf(buf, "-1\n"); |
177 | return sprintf(buf, "%lu\n", result); | 345 | return sprintf(buf, "%lu\n", result); |
178 | } | 346 | } |
@@ -187,7 +355,7 @@ static ssize_t store_ideapad_cam(struct device *dev, | |||
187 | return 0; | 355 | return 0; |
188 | if (sscanf(buf, "%i", &state) != 1) | 356 | if (sscanf(buf, "%i", &state) != 1) |
189 | return -EINVAL; | 357 | return -EINVAL; |
190 | ret = write_ec_cmd(ideapad_handle, 0x1E, state); | 358 | ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state); |
191 | if (ret < 0) | 359 | if (ret < 0) |
192 | return ret; | 360 | return ret; |
193 | return count; | 361 | return count; |
@@ -195,20 +363,8 @@ static ssize_t store_ideapad_cam(struct device *dev, | |||
195 | 363 | ||
196 | static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); | 364 | static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); |
197 | 365 | ||
198 | static ssize_t show_ideapad_cfg(struct device *dev, | ||
199 | struct device_attribute *attr, | ||
200 | char *buf) | ||
201 | { | ||
202 | struct ideapad_private *priv = dev_get_drvdata(dev); | ||
203 | |||
204 | return sprintf(buf, "0x%.8lX\n", priv->cfg); | ||
205 | } | ||
206 | |||
207 | static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL); | ||
208 | |||
209 | static struct attribute *ideapad_attributes[] = { | 366 | static struct attribute *ideapad_attributes[] = { |
210 | &dev_attr_camera_power.attr, | 367 | &dev_attr_camera_power.attr, |
211 | &dev_attr_cfg.attr, | ||
212 | NULL | 368 | NULL |
213 | }; | 369 | }; |
214 | 370 | ||
@@ -244,9 +400,9 @@ struct ideapad_rfk_data { | |||
244 | }; | 400 | }; |
245 | 401 | ||
246 | const struct ideapad_rfk_data ideapad_rfk_data[] = { | 402 | const struct ideapad_rfk_data ideapad_rfk_data[] = { |
247 | { "ideapad_wlan", CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN }, | 403 | { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, |
248 | { "ideapad_bluetooth", CFG_BT_BIT, 0x17, RFKILL_TYPE_BLUETOOTH }, | 404 | { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, |
249 | { "ideapad_3g", CFG_3G_BIT, 0x20, RFKILL_TYPE_WWAN }, | 405 | { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, |
250 | }; | 406 | }; |
251 | 407 | ||
252 | static int ideapad_rfk_set(void *data, bool blocked) | 408 | static int ideapad_rfk_set(void *data, bool blocked) |
@@ -260,13 +416,12 @@ static struct rfkill_ops ideapad_rfk_ops = { | |||
260 | .set_block = ideapad_rfk_set, | 416 | .set_block = ideapad_rfk_set, |
261 | }; | 417 | }; |
262 | 418 | ||
263 | static void ideapad_sync_rfk_state(struct acpi_device *adevice) | 419 | static void ideapad_sync_rfk_state(struct ideapad_private *priv) |
264 | { | 420 | { |
265 | struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); | ||
266 | unsigned long hw_blocked; | 421 | unsigned long hw_blocked; |
267 | int i; | 422 | int i; |
268 | 423 | ||
269 | if (read_ec_data(ideapad_handle, 0x23, &hw_blocked)) | 424 | if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked)) |
270 | return; | 425 | return; |
271 | hw_blocked = !hw_blocked; | 426 | hw_blocked = !hw_blocked; |
272 | 427 | ||
@@ -363,8 +518,10 @@ static void ideapad_platform_exit(struct ideapad_private *priv) | |||
363 | * input device | 518 | * input device |
364 | */ | 519 | */ |
365 | static const struct key_entry ideapad_keymap[] = { | 520 | static const struct key_entry ideapad_keymap[] = { |
366 | { KE_KEY, 0x06, { KEY_SWITCHVIDEOMODE } }, | 521 | { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } }, |
367 | { KE_KEY, 0x0D, { KEY_WLAN } }, | 522 | { KE_KEY, 13, { KEY_WLAN } }, |
523 | { KE_KEY, 16, { KEY_PROG1 } }, | ||
524 | { KE_KEY, 17, { KEY_PROG2 } }, | ||
368 | { KE_END, 0 }, | 525 | { KE_END, 0 }, |
369 | }; | 526 | }; |
370 | 527 | ||
@@ -419,6 +576,18 @@ static void ideapad_input_report(struct ideapad_private *priv, | |||
419 | sparse_keymap_report_event(priv->inputdev, scancode, 1, true); | 576 | sparse_keymap_report_event(priv->inputdev, scancode, 1, true); |
420 | } | 577 | } |
421 | 578 | ||
579 | static void ideapad_input_novokey(struct ideapad_private *priv) | ||
580 | { | ||
581 | unsigned long long_pressed; | ||
582 | |||
583 | if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed)) | ||
584 | return; | ||
585 | if (long_pressed) | ||
586 | ideapad_input_report(priv, 17); | ||
587 | else | ||
588 | ideapad_input_report(priv, 16); | ||
589 | } | ||
590 | |||
422 | /* | 591 | /* |
423 | * backlight | 592 | * backlight |
424 | */ | 593 | */ |
@@ -426,16 +595,17 @@ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev) | |||
426 | { | 595 | { |
427 | unsigned long now; | 596 | unsigned long now; |
428 | 597 | ||
429 | if (read_ec_data(ideapad_handle, 0x12, &now)) | 598 | if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now)) |
430 | return -EIO; | 599 | return -EIO; |
431 | return now; | 600 | return now; |
432 | } | 601 | } |
433 | 602 | ||
434 | static int ideapad_backlight_update_status(struct backlight_device *blightdev) | 603 | static int ideapad_backlight_update_status(struct backlight_device *blightdev) |
435 | { | 604 | { |
436 | if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness)) | 605 | if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL, |
606 | blightdev->props.brightness)) | ||
437 | return -EIO; | 607 | return -EIO; |
438 | if (write_ec_cmd(ideapad_handle, 0x33, | 608 | if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER, |
439 | blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1)) | 609 | blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1)) |
440 | return -EIO; | 610 | return -EIO; |
441 | 611 | ||
@@ -453,11 +623,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv) | |||
453 | struct backlight_properties props; | 623 | struct backlight_properties props; |
454 | unsigned long max, now, power; | 624 | unsigned long max, now, power; |
455 | 625 | ||
456 | if (read_ec_data(ideapad_handle, 0x11, &max)) | 626 | if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max)) |
457 | return -EIO; | 627 | return -EIO; |
458 | if (read_ec_data(ideapad_handle, 0x12, &now)) | 628 | if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now)) |
459 | return -EIO; | 629 | return -EIO; |
460 | if (read_ec_data(ideapad_handle, 0x18, &power)) | 630 | if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power)) |
461 | return -EIO; | 631 | return -EIO; |
462 | 632 | ||
463 | memset(&props, 0, sizeof(struct backlight_properties)); | 633 | memset(&props, 0, sizeof(struct backlight_properties)); |
@@ -493,7 +663,9 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv) | |||
493 | unsigned long power; | 663 | unsigned long power; |
494 | struct backlight_device *blightdev = priv->blightdev; | 664 | struct backlight_device *blightdev = priv->blightdev; |
495 | 665 | ||
496 | if (read_ec_data(ideapad_handle, 0x18, &power)) | 666 | if (!blightdev) |
667 | return; | ||
668 | if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power)) | ||
497 | return; | 669 | return; |
498 | blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; | 670 | blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; |
499 | } | 671 | } |
@@ -504,7 +676,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv) | |||
504 | 676 | ||
505 | /* if we control brightness via acpi video driver */ | 677 | /* if we control brightness via acpi video driver */ |
506 | if (priv->blightdev == NULL) { | 678 | if (priv->blightdev == NULL) { |
507 | read_ec_data(ideapad_handle, 0x12, &now); | 679 | read_ec_data(ideapad_handle, VPCCMD_R_BL, &now); |
508 | return; | 680 | return; |
509 | } | 681 | } |
510 | 682 | ||
@@ -533,6 +705,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) | |||
533 | if (!priv) | 705 | if (!priv) |
534 | return -ENOMEM; | 706 | return -ENOMEM; |
535 | dev_set_drvdata(&adevice->dev, priv); | 707 | dev_set_drvdata(&adevice->dev, priv); |
708 | ideapad_priv = priv; | ||
536 | ideapad_handle = adevice->handle; | 709 | ideapad_handle = adevice->handle; |
537 | priv->cfg = cfg; | 710 | priv->cfg = cfg; |
538 | 711 | ||
@@ -540,6 +713,10 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) | |||
540 | if (ret) | 713 | if (ret) |
541 | goto platform_failed; | 714 | goto platform_failed; |
542 | 715 | ||
716 | ret = ideapad_debugfs_init(priv); | ||
717 | if (ret) | ||
718 | goto debugfs_failed; | ||
719 | |||
543 | ret = ideapad_input_init(priv); | 720 | ret = ideapad_input_init(priv); |
544 | if (ret) | 721 | if (ret) |
545 | goto input_failed; | 722 | goto input_failed; |
@@ -550,7 +727,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) | |||
550 | else | 727 | else |
551 | priv->rfk[i] = NULL; | 728 | priv->rfk[i] = NULL; |
552 | } | 729 | } |
553 | ideapad_sync_rfk_state(adevice); | 730 | ideapad_sync_rfk_state(priv); |
554 | 731 | ||
555 | if (!acpi_video_backlight_support()) { | 732 | if (!acpi_video_backlight_support()) { |
556 | ret = ideapad_backlight_init(priv); | 733 | ret = ideapad_backlight_init(priv); |
@@ -565,6 +742,8 @@ backlight_failed: | |||
565 | ideapad_unregister_rfkill(adevice, i); | 742 | ideapad_unregister_rfkill(adevice, i); |
566 | ideapad_input_exit(priv); | 743 | ideapad_input_exit(priv); |
567 | input_failed: | 744 | input_failed: |
745 | ideapad_debugfs_exit(priv); | ||
746 | debugfs_failed: | ||
568 | ideapad_platform_exit(priv); | 747 | ideapad_platform_exit(priv); |
569 | platform_failed: | 748 | platform_failed: |
570 | kfree(priv); | 749 | kfree(priv); |
@@ -580,6 +759,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type) | |||
580 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 759 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) |
581 | ideapad_unregister_rfkill(adevice, i); | 760 | ideapad_unregister_rfkill(adevice, i); |
582 | ideapad_input_exit(priv); | 761 | ideapad_input_exit(priv); |
762 | ideapad_debugfs_exit(priv); | ||
583 | ideapad_platform_exit(priv); | 763 | ideapad_platform_exit(priv); |
584 | dev_set_drvdata(&adevice->dev, NULL); | 764 | dev_set_drvdata(&adevice->dev, NULL); |
585 | kfree(priv); | 765 | kfree(priv); |
@@ -593,9 +773,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) | |||
593 | acpi_handle handle = adevice->handle; | 773 | acpi_handle handle = adevice->handle; |
594 | unsigned long vpc1, vpc2, vpc_bit; | 774 | unsigned long vpc1, vpc2, vpc_bit; |
595 | 775 | ||
596 | if (read_ec_data(handle, 0x10, &vpc1)) | 776 | if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1)) |
597 | return; | 777 | return; |
598 | if (read_ec_data(handle, 0x1A, &vpc2)) | 778 | if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2)) |
599 | return; | 779 | return; |
600 | 780 | ||
601 | vpc1 = (vpc2 << 8) | vpc1; | 781 | vpc1 = (vpc2 << 8) | vpc1; |
@@ -603,11 +783,14 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) | |||
603 | if (test_bit(vpc_bit, &vpc1)) { | 783 | if (test_bit(vpc_bit, &vpc1)) { |
604 | switch (vpc_bit) { | 784 | switch (vpc_bit) { |
605 | case 9: | 785 | case 9: |
606 | ideapad_sync_rfk_state(adevice); | 786 | ideapad_sync_rfk_state(priv); |
607 | break; | 787 | break; |
608 | case 4: | 788 | case 4: |
609 | ideapad_backlight_notify_brightness(priv); | 789 | ideapad_backlight_notify_brightness(priv); |
610 | break; | 790 | break; |
791 | case 3: | ||
792 | ideapad_input_novokey(priv); | ||
793 | break; | ||
611 | case 2: | 794 | case 2: |
612 | ideapad_backlight_notify_power(priv); | 795 | ideapad_backlight_notify_power(priv); |
613 | break; | 796 | break; |