aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2012-06-01 13:11:22 -0400
committerMatthew Garrett <mjg@redhat.com>2012-07-28 00:06:02 -0400
commit1eb3fe1d3b6b9bf6045eb12f0c3ac12569169870 (patch)
treeb2e6212f64174dee7c57c10d971e70914ba30de9 /drivers/platform
parent63a78bb1051b240417daad3a3fa9c1bb10646dca (diff)
ACER: Add support for accelerometer sensor
This device is present on Iconia Tab W500. Signed-off-by: Marek Vasut <marex@denx.de> Cc: joeyli <jlee@suse.com> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/acer-wmi.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index c8f40c9c0428..175809dd5587 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -95,6 +95,7 @@ MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
95 95
96enum acer_wmi_event_ids { 96enum acer_wmi_event_ids {
97 WMID_HOTKEY_EVENT = 0x1, 97 WMID_HOTKEY_EVENT = 0x1,
98 WMID_ACCEL_EVENT = 0x5,
98}; 99};
99 100
100static const struct key_entry acer_wmi_keymap[] = { 101static const struct key_entry acer_wmi_keymap[] = {
@@ -130,6 +131,7 @@ static const struct key_entry acer_wmi_keymap[] = {
130}; 131};
131 132
132static struct input_dev *acer_wmi_input_dev; 133static struct input_dev *acer_wmi_input_dev;
134static struct input_dev *acer_wmi_accel_dev;
133 135
134struct event_return_value { 136struct event_return_value {
135 u8 function; 137 u8 function;
@@ -200,6 +202,7 @@ struct hotkey_function_type_aa {
200#define ACER_CAP_BLUETOOTH (1<<2) 202#define ACER_CAP_BLUETOOTH (1<<2)
201#define ACER_CAP_BRIGHTNESS (1<<3) 203#define ACER_CAP_BRIGHTNESS (1<<3)
202#define ACER_CAP_THREEG (1<<4) 204#define ACER_CAP_THREEG (1<<4)
205#define ACER_CAP_ACCEL (1<<5)
203#define ACER_CAP_ANY (0xFFFFFFFF) 206#define ACER_CAP_ANY (0xFFFFFFFF)
204 207
205/* 208/*
@@ -1399,6 +1402,60 @@ static void acer_backlight_exit(void)
1399} 1402}
1400 1403
1401/* 1404/*
1405 * Accelerometer device
1406 */
1407static acpi_handle gsensor_handle;
1408
1409static int acer_gsensor_init(void)
1410{
1411 acpi_status status;
1412 struct acpi_buffer output;
1413 union acpi_object out_obj;
1414
1415 output.length = sizeof(out_obj);
1416 output.pointer = &out_obj;
1417 status = acpi_evaluate_object(gsensor_handle, "_INI", NULL, &output);
1418 if (ACPI_FAILURE(status))
1419 return -1;
1420
1421 return 0;
1422}
1423
1424static int acer_gsensor_open(struct input_dev *input)
1425{
1426 return acer_gsensor_init();
1427}
1428
1429static int acer_gsensor_event(void)
1430{
1431 acpi_status status;
1432 struct acpi_buffer output;
1433 union acpi_object out_obj[5];
1434
1435 if (!has_cap(ACER_CAP_ACCEL))
1436 return -1;
1437
1438 output.length = sizeof(out_obj);
1439 output.pointer = out_obj;
1440
1441 status = acpi_evaluate_object(gsensor_handle, "RDVL", NULL, &output);
1442 if (ACPI_FAILURE(status))
1443 return -1;
1444
1445 if (out_obj->package.count != 4)
1446 return -1;
1447
1448 input_report_abs(acer_wmi_accel_dev, ABS_X,
1449 (s16)out_obj->package.elements[0].integer.value);
1450 input_report_abs(acer_wmi_accel_dev, ABS_Y,
1451 (s16)out_obj->package.elements[1].integer.value);
1452 input_report_abs(acer_wmi_accel_dev, ABS_Z,
1453 (s16)out_obj->package.elements[2].integer.value);
1454 input_sync(acer_wmi_accel_dev);
1455 return 0;
1456}
1457
1458/*
1402 * Rfkill devices 1459 * Rfkill devices
1403 */ 1460 */
1404static void acer_rfkill_update(struct work_struct *ignored); 1461static void acer_rfkill_update(struct work_struct *ignored);
@@ -1673,6 +1730,9 @@ static void acer_wmi_notify(u32 value, void *context)
1673 1, true); 1730 1, true);
1674 } 1731 }
1675 break; 1732 break;
1733 case WMID_ACCEL_EVENT:
1734 acer_gsensor_event();
1735 break;
1676 default: 1736 default:
1677 pr_warn("Unknown function number - %d - %d\n", 1737 pr_warn("Unknown function number - %d - %d\n",
1678 return_value.function, return_value.key_num); 1738 return_value.function, return_value.key_num);
@@ -1758,6 +1818,74 @@ static int acer_wmi_enable_lm(void)
1758 return status; 1818 return status;
1759} 1819}
1760 1820
1821static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level,
1822 void *ctx, void **retval)
1823{
1824 *(acpi_handle *)retval = ah;
1825 return AE_OK;
1826}
1827
1828static int __init acer_wmi_get_handle(const char *name, const char *prop,
1829 acpi_handle *ah)
1830{
1831 acpi_status status;
1832 acpi_handle handle;
1833
1834 BUG_ON(!name || !ah);
1835
1836 handle = 0;
1837 status = acpi_get_devices(prop, acer_wmi_get_handle_cb,
1838 (void *)name, &handle);
1839
1840 if (ACPI_SUCCESS(status)) {
1841 *ah = handle;
1842 return 0;
1843 } else {
1844 return -ENODEV;
1845 }
1846}
1847
1848static int __init acer_wmi_accel_setup(void)
1849{
1850 int err;
1851
1852 err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle);
1853 if (err)
1854 return err;
1855
1856 interface->capability |= ACER_CAP_ACCEL;
1857
1858 acer_wmi_accel_dev = input_allocate_device();
1859 if (!acer_wmi_accel_dev)
1860 return -ENOMEM;
1861
1862 acer_wmi_accel_dev->open = acer_gsensor_open;
1863
1864 acer_wmi_accel_dev->name = "Acer BMA150 accelerometer";
1865 acer_wmi_accel_dev->phys = "wmi/input1";
1866 acer_wmi_accel_dev->id.bustype = BUS_HOST;
1867 acer_wmi_accel_dev->evbit[0] = BIT_MASK(EV_ABS);
1868 input_set_abs_params(acer_wmi_accel_dev, ABS_X, -16384, 16384, 0, 0);
1869 input_set_abs_params(acer_wmi_accel_dev, ABS_Y, -16384, 16384, 0, 0);
1870 input_set_abs_params(acer_wmi_accel_dev, ABS_Z, -16384, 16384, 0, 0);
1871
1872 err = input_register_device(acer_wmi_accel_dev);
1873 if (err)
1874 goto err_free_dev;
1875
1876 return 0;
1877
1878err_free_dev:
1879 input_free_device(acer_wmi_accel_dev);
1880 return err;
1881}
1882
1883static void acer_wmi_accel_destroy(void)
1884{
1885 input_unregister_device(acer_wmi_accel_dev);
1886 input_free_device(acer_wmi_accel_dev);
1887}
1888
1761static int __init acer_wmi_input_setup(void) 1889static int __init acer_wmi_input_setup(void)
1762{ 1890{
1763 acpi_status status; 1891 acpi_status status;
@@ -1912,6 +2040,9 @@ static int acer_resume(struct device *dev)
1912 if (has_cap(ACER_CAP_BRIGHTNESS)) 2040 if (has_cap(ACER_CAP_BRIGHTNESS))
1913 set_u32(data->brightness, ACER_CAP_BRIGHTNESS); 2041 set_u32(data->brightness, ACER_CAP_BRIGHTNESS);
1914 2042
2043 if (has_cap(ACER_CAP_ACCEL))
2044 acer_gsensor_init();
2045
1915 return 0; 2046 return 0;
1916} 2047}
1917 2048
@@ -2090,6 +2221,8 @@ static int __init acer_wmi_init(void)
2090 return err; 2221 return err;
2091 } 2222 }
2092 2223
2224 acer_wmi_accel_setup();
2225
2093 err = platform_driver_register(&acer_platform_driver); 2226 err = platform_driver_register(&acer_platform_driver);
2094 if (err) { 2227 if (err) {
2095 pr_err("Unable to register platform driver\n"); 2228 pr_err("Unable to register platform driver\n");
@@ -2133,6 +2266,8 @@ error_device_alloc:
2133error_platform_register: 2266error_platform_register:
2134 if (wmi_has_guid(ACERWMID_EVENT_GUID)) 2267 if (wmi_has_guid(ACERWMID_EVENT_GUID))
2135 acer_wmi_input_destroy(); 2268 acer_wmi_input_destroy();
2269 if (has_cap(ACER_CAP_ACCEL))
2270 acer_wmi_accel_destroy();
2136 2271
2137 return err; 2272 return err;
2138} 2273}
@@ -2142,6 +2277,9 @@ static void __exit acer_wmi_exit(void)
2142 if (wmi_has_guid(ACERWMID_EVENT_GUID)) 2277 if (wmi_has_guid(ACERWMID_EVENT_GUID))
2143 acer_wmi_input_destroy(); 2278 acer_wmi_input_destroy();
2144 2279
2280 if (has_cap(ACER_CAP_ACCEL))
2281 acer_wmi_accel_destroy();
2282
2145 remove_sysfs(acer_platform_device); 2283 remove_sysfs(acer_platform_device);
2146 remove_debugfs(); 2284 remove_debugfs();
2147 platform_device_unregister(acer_platform_device); 2285 platform_device_unregister(acer_platform_device);