aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/sony-laptop.c97
1 files changed, 81 insertions, 16 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 6db1661a5625..516dd22bbb26 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -727,20 +727,79 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
727 return -1; 727 return -1;
728} 728}
729 729
730static int sony_find_snc_handle(int handle) 730struct sony_nc_handles {
731 u16 cap[0x10];
732 struct device_attribute devattr;
733};
734
735struct sony_nc_handles *handles;
736
737static ssize_t sony_nc_handles_show(struct device *dev,
738 struct device_attribute *attr, char *buffer)
739{
740 ssize_t len = 0;
741 int i;
742
743 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
744 len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
745 handles->cap[i]);
746 }
747 len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
748
749 return len;
750}
751
752static int sony_nc_handles_setup(struct platform_device *pd)
731{ 753{
732 int i; 754 int i;
733 int result; 755 int result;
734 756
735 for (i = 0x20; i < 0x30; i++) { 757 handles = kzalloc(sizeof(*handles), GFP_KERNEL);
736 acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); 758
737 if (result == handle) { 759 sysfs_attr_init(&handles->devattr.attr);
738 dprintk("found handle 0x%.4x (offset: 0x%.2x)\n", 760 handles->devattr.attr.name = "handles";
739 handle, i - 0x20); 761 handles->devattr.attr.mode = S_IRUGO;
740 return i-0x20; 762 handles->devattr.show = sony_nc_handles_show;
763
764 for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
765 if (!acpi_callsetfunc(sony_nc_acpi_handle,
766 "SN00", i + 0x20, &result)) {
767 dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
768 result, i);
769 handles->cap[i] = result;
741 } 770 }
742 } 771 }
743 772
773 /* allow reading capabilities via sysfs */
774 if (device_create_file(&pd->dev, &handles->devattr)) {
775 kfree(handles);
776 handles = NULL;
777 return -1;
778 }
779
780 return 0;
781}
782
783static int sony_nc_handles_cleanup(struct platform_device *pd)
784{
785 if (handles) {
786 device_remove_file(&pd->dev, &handles->devattr);
787 kfree(handles);
788 handles = NULL;
789 }
790 return 0;
791}
792
793static int sony_find_snc_handle(int handle)
794{
795 int i;
796 for (i = 0; i < 0x10; i++) {
797 if (handles->cap[i] == handle) {
798 dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
799 handle, i);
800 return i;
801 }
802 }
744 dprintk("handle 0x%.4x not found\n", handle); 803 dprintk("handle 0x%.4x not found\n", handle);
745 return -1; 804 return -1;
746} 805}
@@ -1274,6 +1333,10 @@ static int sony_nc_add(struct acpi_device *device)
1274 goto outwalk; 1333 goto outwalk;
1275 } 1334 }
1276 1335
1336 result = sony_pf_add();
1337 if (result)
1338 goto outpresent;
1339
1277 if (debug) { 1340 if (debug) {
1278 status = acpi_walk_namespace(ACPI_TYPE_METHOD, 1341 status = acpi_walk_namespace(ACPI_TYPE_METHOD,
1279 sony_nc_acpi_handle, 1, sony_walk_callback, 1342 sony_nc_acpi_handle, 1, sony_walk_callback,
@@ -1281,7 +1344,7 @@ static int sony_nc_add(struct acpi_device *device)
1281 if (ACPI_FAILURE(status)) { 1344 if (ACPI_FAILURE(status)) {
1282 pr_warn(DRV_PFX "unable to walk acpi resources\n"); 1345 pr_warn(DRV_PFX "unable to walk acpi resources\n");
1283 result = -ENODEV; 1346 result = -ENODEV;
1284 goto outwalk; 1347 goto outpresent;
1285 } 1348 }
1286 } 1349 }
1287 1350
@@ -1294,6 +1357,8 @@ static int sony_nc_add(struct acpi_device *device)
1294 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", 1357 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1295 &handle))) { 1358 &handle))) {
1296 dprintk("Doing SNC setup\n"); 1359 dprintk("Doing SNC setup\n");
1360 if (sony_nc_handles_setup(sony_pf_device))
1361 goto outpresent;
1297 sony_nc_function_setup(device); 1362 sony_nc_function_setup(device);
1298 sony_nc_rfkill_setup(device); 1363 sony_nc_rfkill_setup(device);
1299 } 1364 }
@@ -1302,7 +1367,7 @@ static int sony_nc_add(struct acpi_device *device)
1302 result = sony_laptop_setup_input(device); 1367 result = sony_laptop_setup_input(device);
1303 if (result) { 1368 if (result) {
1304 pr_err(DRV_PFX "Unable to create input devices.\n"); 1369 pr_err(DRV_PFX "Unable to create input devices.\n");
1305 goto outwalk; 1370 goto outsnc;
1306 } 1371 }
1307 1372
1308 if (acpi_video_backlight_support()) { 1373 if (acpi_video_backlight_support()) {
@@ -1330,10 +1395,6 @@ static int sony_nc_add(struct acpi_device *device)
1330 1395
1331 } 1396 }
1332 1397
1333 result = sony_pf_add();
1334 if (result)
1335 goto outbacklight;
1336
1337 /* create sony_pf sysfs attributes related to the SNC device */ 1398 /* create sony_pf sysfs attributes related to the SNC device */
1338 for (item = sony_nc_values; item->name; ++item) { 1399 for (item = sony_nc_values; item->name; ++item) {
1339 1400
@@ -1379,14 +1440,17 @@ static int sony_nc_add(struct acpi_device *device)
1379 for (item = sony_nc_values; item->name; ++item) { 1440 for (item = sony_nc_values; item->name; ++item) {
1380 device_remove_file(&sony_pf_device->dev, &item->devattr); 1441 device_remove_file(&sony_pf_device->dev, &item->devattr);
1381 } 1442 }
1382 sony_pf_remove();
1383
1384 outbacklight:
1385 if (sony_backlight_device) 1443 if (sony_backlight_device)
1386 backlight_device_unregister(sony_backlight_device); 1444 backlight_device_unregister(sony_backlight_device);
1387 1445
1388 sony_laptop_remove_input(); 1446 sony_laptop_remove_input();
1389 1447
1448 outsnc:
1449 sony_nc_handles_cleanup(sony_pf_device);
1450
1451 outpresent:
1452 sony_pf_remove();
1453
1390 outwalk: 1454 outwalk:
1391 sony_nc_rfkill_cleanup(); 1455 sony_nc_rfkill_cleanup();
1392 return result; 1456 return result;
@@ -1405,6 +1469,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
1405 device_remove_file(&sony_pf_device->dev, &item->devattr); 1469 device_remove_file(&sony_pf_device->dev, &item->devattr);
1406 } 1470 }
1407 1471
1472 sony_nc_handles_cleanup(sony_pf_device);
1408 sony_pf_remove(); 1473 sony_pf_remove();
1409 sony_laptop_remove_input(); 1474 sony_laptop_remove_input();
1410 sony_nc_rfkill_cleanup(); 1475 sony_nc_rfkill_cleanup();