aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/sony-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r--drivers/platform/x86/sony-laptop.c65
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
141static void sony_nc_kbd_backlight_resume(void);
142
141enum sony_nc_rfkill { 143enum 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)
798static int sony_nc_handles_cleanup(struct platform_device *pd) 802static 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)
808static int sony_find_snc_handle(int handle) 813static 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
1360struct kbd_backlight { 1374struct 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:
1501static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd) 1519static 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
1536static 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
1511static void sony_nc_backlight_setup(void) 1552static void sony_nc_backlight_setup(void)
1512{ 1553{
1513 acpi_handle unused; 1554 acpi_handle unused;