diff options
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index e642f5f29504..8f709aec4da0 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -138,6 +138,8 @@ MODULE_PARM_DESC(kbd_backlight_timeout, | |||
138 | "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout " | 138 | "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout " |
139 | "(default: 0)"); | 139 | "(default: 0)"); |
140 | 140 | ||
141 | static void sony_nc_kbd_backlight_resume(void); | ||
142 | |||
141 | enum sony_nc_rfkill { | 143 | enum sony_nc_rfkill { |
142 | SONY_WIFI, | 144 | SONY_WIFI, |
143 | SONY_BLUETOOTH, | 145 | SONY_BLUETOOTH, |
@@ -771,11 +773,6 @@ static int sony_nc_handles_setup(struct platform_device *pd) | |||
771 | if (!handles) | 773 | if (!handles) |
772 | return -ENOMEM; | 774 | return -ENOMEM; |
773 | 775 | ||
774 | sysfs_attr_init(&handles->devattr.attr); | ||
775 | handles->devattr.attr.name = "handles"; | ||
776 | handles->devattr.attr.mode = S_IRUGO; | ||
777 | handles->devattr.show = sony_nc_handles_show; | ||
778 | |||
779 | for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { | 776 | for (i = 0; i < ARRAY_SIZE(handles->cap); i++) { |
780 | if (!acpi_callsetfunc(sony_nc_acpi_handle, | 777 | if (!acpi_callsetfunc(sony_nc_acpi_handle, |
781 | "SN00", i + 0x20, &result)) { | 778 | "SN00", i + 0x20, &result)) { |
@@ -785,11 +782,18 @@ static int sony_nc_handles_setup(struct platform_device *pd) | |||
785 | } | 782 | } |
786 | } | 783 | } |
787 | 784 | ||
788 | /* allow reading capabilities via sysfs */ | 785 | if (debug) { |
789 | if (device_create_file(&pd->dev, &handles->devattr)) { | 786 | sysfs_attr_init(&handles->devattr.attr); |
790 | kfree(handles); | 787 | handles->devattr.attr.name = "handles"; |
791 | handles = NULL; | 788 | handles->devattr.attr.mode = S_IRUGO; |
792 | return -1; | 789 | handles->devattr.show = sony_nc_handles_show; |
790 | |||
791 | /* allow reading capabilities via sysfs */ | ||
792 | if (device_create_file(&pd->dev, &handles->devattr)) { | ||
793 | kfree(handles); | ||
794 | handles = NULL; | ||
795 | return -1; | ||
796 | } | ||
793 | } | 797 | } |
794 | 798 | ||
795 | return 0; | 799 | return 0; |
@@ -798,7 +802,8 @@ static int sony_nc_handles_setup(struct platform_device *pd) | |||
798 | static int sony_nc_handles_cleanup(struct platform_device *pd) | 802 | static int sony_nc_handles_cleanup(struct platform_device *pd) |
799 | { | 803 | { |
800 | if (handles) { | 804 | if (handles) { |
801 | device_remove_file(&pd->dev, &handles->devattr); | 805 | if (debug) |
806 | device_remove_file(&pd->dev, &handles->devattr); | ||
802 | kfree(handles); | 807 | kfree(handles); |
803 | handles = NULL; | 808 | handles = NULL; |
804 | } | 809 | } |
@@ -808,6 +813,11 @@ static int sony_nc_handles_cleanup(struct platform_device *pd) | |||
808 | static int sony_find_snc_handle(int handle) | 813 | static int sony_find_snc_handle(int handle) |
809 | { | 814 | { |
810 | int i; | 815 | int i; |
816 | |||
817 | /* not initialized yet, return early */ | ||
818 | if (!handles) | ||
819 | return -1; | ||
820 | |||
811 | for (i = 0; i < 0x10; i++) { | 821 | for (i = 0; i < 0x10; i++) { |
812 | if (handles->cap[i] == handle) { | 822 | if (handles->cap[i] == handle) { |
813 | dprintk("found handle 0x%.4x (offset: 0x%.2x)\n", | 823 | dprintk("found handle 0x%.4x (offset: 0x%.2x)\n", |
@@ -1168,6 +1178,9 @@ static int sony_nc_resume(struct acpi_device *device) | |||
1168 | /* re-read rfkill state */ | 1178 | /* re-read rfkill state */ |
1169 | sony_nc_rfkill_update(); | 1179 | sony_nc_rfkill_update(); |
1170 | 1180 | ||
1181 | /* restore kbd backlight states */ | ||
1182 | sony_nc_kbd_backlight_resume(); | ||
1183 | |||
1171 | return 0; | 1184 | return 0; |
1172 | } | 1185 | } |
1173 | 1186 | ||
@@ -1355,6 +1368,7 @@ out_no_enum: | |||
1355 | #define KBDBL_HANDLER 0x137 | 1368 | #define KBDBL_HANDLER 0x137 |
1356 | #define KBDBL_PRESENT 0xB00 | 1369 | #define KBDBL_PRESENT 0xB00 |
1357 | #define SET_MODE 0xC00 | 1370 | #define SET_MODE 0xC00 |
1371 | #define SET_STATE 0xD00 | ||
1358 | #define SET_TIMEOUT 0xE00 | 1372 | #define SET_TIMEOUT 0xE00 |
1359 | 1373 | ||
1360 | struct kbd_backlight { | 1374 | struct kbd_backlight { |
@@ -1377,6 +1391,10 @@ static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value) | |||
1377 | (value << 0x10) | SET_MODE, &result)) | 1391 | (value << 0x10) | SET_MODE, &result)) |
1378 | return -EIO; | 1392 | return -EIO; |
1379 | 1393 | ||
1394 | /* Try to turn the light on/off immediately */ | ||
1395 | sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE, | ||
1396 | &result); | ||
1397 | |||
1380 | kbdbl_handle->mode = value; | 1398 | kbdbl_handle->mode = value; |
1381 | 1399 | ||
1382 | return 0; | 1400 | return 0; |
@@ -1458,7 +1476,7 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd) | |||
1458 | { | 1476 | { |
1459 | int result; | 1477 | int result; |
1460 | 1478 | ||
1461 | if (sony_call_snc_handle(0x137, KBDBL_PRESENT, &result)) | 1479 | if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result)) |
1462 | return 0; | 1480 | return 0; |
1463 | if (!(result & 0x02)) | 1481 | if (!(result & 0x02)) |
1464 | return 0; | 1482 | return 0; |
@@ -1501,13 +1519,36 @@ outkzalloc: | |||
1501 | static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) | 1519 | static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) |
1502 | { | 1520 | { |
1503 | if (kbdbl_handle) { | 1521 | if (kbdbl_handle) { |
1522 | int result; | ||
1523 | |||
1504 | device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); | 1524 | device_remove_file(&pd->dev, &kbdbl_handle->mode_attr); |
1505 | device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr); | 1525 | device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr); |
1526 | |||
1527 | /* restore the default hw behaviour */ | ||
1528 | sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result); | ||
1529 | sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result); | ||
1530 | |||
1506 | kfree(kbdbl_handle); | 1531 | kfree(kbdbl_handle); |
1507 | } | 1532 | } |
1508 | return 0; | 1533 | return 0; |
1509 | } | 1534 | } |
1510 | 1535 | ||
1536 | static void sony_nc_kbd_backlight_resume(void) | ||
1537 | { | ||
1538 | int ignore = 0; | ||
1539 | |||
1540 | if (!kbdbl_handle) | ||
1541 | return; | ||
1542 | |||
1543 | if (kbdbl_handle->mode == 0) | ||
1544 | sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore); | ||
1545 | |||
1546 | if (kbdbl_handle->timeout != 0) | ||
1547 | sony_call_snc_handle(KBDBL_HANDLER, | ||
1548 | (kbdbl_handle->timeout << 0x10) | SET_TIMEOUT, | ||
1549 | &ignore); | ||
1550 | } | ||
1551 | |||
1511 | static void sony_nc_backlight_setup(void) | 1552 | static void sony_nc_backlight_setup(void) |
1512 | { | 1553 | { |
1513 | acpi_handle unused; | 1554 | acpi_handle unused; |