|
@@ -727,20 +727,79 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
-static int sony_find_snc_handle(int handle)
|
|
|
+struct sony_nc_handles {
|
|
|
+ u16 cap[0x10];
|
|
|
+ struct device_attribute devattr;
|
|
|
+};
|
|
|
+
|
|
|
+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) {
|
|
|
- dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
|
|
|
- handle, i - 0x20);
|
|
|
- return i-0x20;
|
|
|
+ handles = kzalloc(sizeof(*handles), GFP_KERNEL);
|
|
|
+
|
|
|
+ sysfs_attr_init(&handles->devattr.attr);
|
|
|
+ handles->devattr.attr.name = "handles";
|
|
|
+ handles->devattr.attr.mode = S_IRUGO;
|
|
|
+ handles->devattr.show = sony_nc_handles_show;
|
|
|
+
|
|
|
+ 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;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* 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) {
|
|
|
+ device_remove_file(&pd->dev, &handles->devattr);
|
|
|
+ kfree(handles);
|
|
|
+ handles = NULL;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int sony_find_snc_handle(int handle)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ 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;
|
|
|
}
|
|
@@ -1274,6 +1333,10 @@ 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,
|
|
@@ -1281,7 +1344,7 @@ static int sony_nc_add(struct acpi_device *device)
|
|
|
if (ACPI_FAILURE(status)) {
|
|
|
pr_warn(DRV_PFX "unable to walk acpi resources\n");
|
|
|
result = -ENODEV;
|
|
|
- goto outwalk;
|
|
|
+ goto outpresent;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1294,6 +1357,8 @@ 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");
|
|
|
+ if (sony_nc_handles_setup(sony_pf_device))
|
|
|
+ goto outpresent;
|
|
|
sony_nc_function_setup(device);
|
|
|
sony_nc_rfkill_setup(device);
|
|
|
}
|
|
@@ -1302,7 +1367,7 @@ static int sony_nc_add(struct acpi_device *device)
|
|
|
result = sony_laptop_setup_input(device);
|
|
|
if (result) {
|
|
|
pr_err(DRV_PFX "Unable to create input devices.\n");
|
|
|
- goto outwalk;
|
|
|
+ goto outsnc;
|
|
|
}
|
|
|
|
|
|
if (acpi_video_backlight_support()) {
|
|
@@ -1330,10 +1395,6 @@ static int sony_nc_add(struct acpi_device *device)
|
|
|
|
|
|
}
|
|
|
|
|
|
- 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) {
|
|
|
|
|
@@ -1379,14 +1440,17 @@ 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_laptop_remove_input();
|
|
|
|
|
|
+ outsnc:
|
|
|
+ sony_nc_handles_cleanup(sony_pf_device);
|
|
|
+
|
|
|
+ outpresent:
|
|
|
+ sony_pf_remove();
|
|
|
+
|
|
|
outwalk:
|
|
|
sony_nc_rfkill_cleanup();
|
|
|
return result;
|
|
@@ -1405,6 +1469,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
|
|
|
device_remove_file(&sony_pf_device->dev, &item->devattr);
|
|
|
}
|
|
|
|
|
|
+ sony_nc_handles_cleanup(sony_pf_device);
|
|
|
sony_pf_remove();
|
|
|
sony_laptop_remove_input();
|
|
|
sony_nc_rfkill_cleanup();
|