diff options
author | Marco Chiappero <marco@absence.it> | 2012-05-19 09:36:00 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2012-05-31 14:35:06 -0400 |
commit | 2b8791c4ff88f774dde98f12f652d5c2bdd2925d (patch) | |
tree | bc728e98a6dc2e95dc12b3a04971d1a08dbaa549 /drivers/platform/x86/sony-laptop.c | |
parent | 2e52631127ceae2508ca5ae6b0870c024f966299 (diff) |
sony-laptop: add touchpad enable/disable function
This setting is stored in the EC and available across reboots.
[malattia@linux.it: group function specific variables in a struct, use
kstrtoul]
Signed-off-by: Marco Chiappero <marco@absence.it>
Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5902bb5a9e78..210d4ae547c2 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -159,6 +159,10 @@ static void sony_nc_lid_resume_cleanup(struct platform_device *pd); | |||
159 | static int sony_nc_highspeed_charging_setup(struct platform_device *pd); | 159 | static int sony_nc_highspeed_charging_setup(struct platform_device *pd); |
160 | static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); | 160 | static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); |
161 | 161 | ||
162 | static int sony_nc_touchpad_setup(struct platform_device *pd, | ||
163 | unsigned int handle); | ||
164 | static void sony_nc_touchpad_cleanup(struct platform_device *pd); | ||
165 | |||
162 | enum sony_nc_rfkill { | 166 | enum sony_nc_rfkill { |
163 | SONY_WIFI, | 167 | SONY_WIFI, |
164 | SONY_BLUETOOTH, | 168 | SONY_BLUETOOTH, |
@@ -1290,6 +1294,14 @@ static void sony_nc_function_setup(struct acpi_device *device, | |||
1290 | /* setup hotkeys */ | 1294 | /* setup hotkeys */ |
1291 | sony_call_snc_handle(handle, 0x100, &result); | 1295 | sony_call_snc_handle(handle, 0x100, &result); |
1292 | break; | 1296 | break; |
1297 | case 0x0105: | ||
1298 | case 0x0148: | ||
1299 | /* touchpad enable/disable */ | ||
1300 | result = sony_nc_touchpad_setup(pf_device, handle); | ||
1301 | if (result) | ||
1302 | pr_err("couldn't set up touchpad control function (%d)\n", | ||
1303 | result); | ||
1304 | break; | ||
1293 | case 0x0115: | 1305 | case 0x0115: |
1294 | case 0x0136: | 1306 | case 0x0136: |
1295 | case 0x013f: | 1307 | case 0x013f: |
@@ -1359,6 +1371,10 @@ static void sony_nc_function_cleanup(struct platform_device *pd) | |||
1359 | continue; | 1371 | continue; |
1360 | 1372 | ||
1361 | switch (handle) { | 1373 | switch (handle) { |
1374 | case 0x0105: | ||
1375 | case 0x0148: | ||
1376 | sony_nc_touchpad_cleanup(pd); | ||
1377 | break; | ||
1362 | case 0x0115: | 1378 | case 0x0115: |
1363 | case 0x0136: | 1379 | case 0x0136: |
1364 | case 0x013f: | 1380 | case 0x013f: |
@@ -2376,6 +2392,81 @@ static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd) | |||
2376 | } | 2392 | } |
2377 | } | 2393 | } |
2378 | 2394 | ||
2395 | /* Touchpad enable/disable */ | ||
2396 | struct touchpad_control { | ||
2397 | struct device_attribute attr; | ||
2398 | int handle; | ||
2399 | }; | ||
2400 | static struct touchpad_control *tp_ctl; | ||
2401 | |||
2402 | static ssize_t sony_nc_touchpad_store(struct device *dev, | ||
2403 | struct device_attribute *attr, const char *buffer, size_t count) | ||
2404 | { | ||
2405 | unsigned int result; | ||
2406 | unsigned long value; | ||
2407 | |||
2408 | if (count > 31) | ||
2409 | return -EINVAL; | ||
2410 | |||
2411 | if (kstrtoul(buffer, 10, &value) || value > 1) | ||
2412 | return -EINVAL; | ||
2413 | |||
2414 | /* sysfs: 0 disabled, 1 enabled | ||
2415 | * EC: 0 enabled, 1 disabled | ||
2416 | */ | ||
2417 | if (sony_call_snc_handle(tp_ctl->handle, | ||
2418 | (!value << 0x10) | 0x100, &result)) | ||
2419 | return -EIO; | ||
2420 | |||
2421 | return count; | ||
2422 | } | ||
2423 | |||
2424 | static ssize_t sony_nc_touchpad_show(struct device *dev, | ||
2425 | struct device_attribute *attr, char *buffer) | ||
2426 | { | ||
2427 | unsigned int result; | ||
2428 | |||
2429 | if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result)) | ||
2430 | return -EINVAL; | ||
2431 | |||
2432 | return snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01)); | ||
2433 | } | ||
2434 | |||
2435 | static int sony_nc_touchpad_setup(struct platform_device *pd, | ||
2436 | unsigned int handle) | ||
2437 | { | ||
2438 | int ret = 0; | ||
2439 | |||
2440 | tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL); | ||
2441 | if (!tp_ctl) | ||
2442 | return -ENOMEM; | ||
2443 | |||
2444 | tp_ctl->handle = handle; | ||
2445 | |||
2446 | sysfs_attr_init(&tp_ctl->attr.attr); | ||
2447 | tp_ctl->attr.attr.name = "touchpad"; | ||
2448 | tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR; | ||
2449 | tp_ctl->attr.show = sony_nc_touchpad_show; | ||
2450 | tp_ctl->attr.store = sony_nc_touchpad_store; | ||
2451 | |||
2452 | ret = device_create_file(&pd->dev, &tp_ctl->attr); | ||
2453 | if (ret) { | ||
2454 | kfree(tp_ctl); | ||
2455 | tp_ctl = NULL; | ||
2456 | } | ||
2457 | |||
2458 | return ret; | ||
2459 | } | ||
2460 | |||
2461 | static void sony_nc_touchpad_cleanup(struct platform_device *pd) | ||
2462 | { | ||
2463 | if (tp_ctl) { | ||
2464 | device_remove_file(&pd->dev, &tp_ctl->attr); | ||
2465 | kfree(tp_ctl); | ||
2466 | tp_ctl = NULL; | ||
2467 | } | ||
2468 | } | ||
2469 | |||
2379 | static void sony_nc_backlight_ng_read_limits(int handle, | 2470 | static void sony_nc_backlight_ng_read_limits(int handle, |
2380 | struct sony_backlight_props *props) | 2471 | struct sony_backlight_props *props) |
2381 | { | 2472 | { |