aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/sony-laptop.c
diff options
context:
space:
mode:
authorMarco Chiappero <marco@absence.it>2012-05-19 09:36:00 -0400
committerMatthew Garrett <mjg@redhat.com>2012-05-31 14:35:06 -0400
commit2b8791c4ff88f774dde98f12f652d5c2bdd2925d (patch)
treebc728e98a6dc2e95dc12b3a04971d1a08dbaa549 /drivers/platform/x86/sony-laptop.c
parent2e52631127ceae2508ca5ae6b0870c024f966299 (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.c91
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);
159static int sony_nc_highspeed_charging_setup(struct platform_device *pd); 159static int sony_nc_highspeed_charging_setup(struct platform_device *pd);
160static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); 160static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd);
161 161
162static int sony_nc_touchpad_setup(struct platform_device *pd,
163 unsigned int handle);
164static void sony_nc_touchpad_cleanup(struct platform_device *pd);
165
162enum sony_nc_rfkill { 166enum 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 */
2396struct touchpad_control {
2397 struct device_attribute attr;
2398 int handle;
2399};
2400static struct touchpad_control *tp_ctl;
2401
2402static 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
2424static 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
2435static 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
2461static 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
2379static void sony_nc_backlight_ng_read_limits(int handle, 2470static void sony_nc_backlight_ng_read_limits(int handle,
2380 struct sony_backlight_props *props) 2471 struct sony_backlight_props *props)
2381{ 2472{