aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
authorAzael Avalos <coproscefalo@gmail.com>2014-03-25 22:38:34 -0400
committerMatthew Garrett <matthew.garrett@nebula.com>2014-04-06 12:58:14 -0400
commit5a2813e97ae6e5d8c521ace7dd2f4106a9d19e71 (patch)
treee2646271a809de88124bd30511d4b98814555476 /drivers/platform/x86
parentdef6c4e25d31b874b939bd08e7941eaa9711653f (diff)
toshiba_acpi: Add accelerometer support
Recent Toshiba laptops now come equiped with a built in accelerometer (TOS620A) device, but such device does not expose the axes information, however, HCI calls 0x006d and 0x00a6 can be used to query such info. This patch adds support to read the axes values by exposing them through the _position_ sysfs file. Signed-off-by: Azael Avalos <coproscefalo@gmail.com> Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/toshiba_acpi.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index c8e8bfb78c19..c971b0fae4c4 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -97,6 +97,8 @@ MODULE_LICENSE("GPL");
97#define HCI_FAILURE 0x1000 97#define HCI_FAILURE 0x1000
98#define HCI_NOT_SUPPORTED 0x8000 98#define HCI_NOT_SUPPORTED 0x8000
99#define HCI_EMPTY 0x8c00 99#define HCI_EMPTY 0x8c00
100#define HCI_DATA_NOT_AVAILABLE 0x8d20
101#define HCI_NOT_INITIALIZED 0x8d50
100#define SCI_OPEN_CLOSE_OK 0x0044 102#define SCI_OPEN_CLOSE_OK 0x0044
101#define SCI_ALREADY_OPEN 0x8100 103#define SCI_ALREADY_OPEN 0x8100
102#define SCI_NOT_OPENED 0x8200 104#define SCI_NOT_OPENED 0x8200
@@ -111,13 +113,16 @@ MODULE_LICENSE("GPL");
111#define HCI_HOTKEY_EVENT 0x001e 113#define HCI_HOTKEY_EVENT 0x001e
112#define HCI_LCD_BRIGHTNESS 0x002a 114#define HCI_LCD_BRIGHTNESS 0x002a
113#define HCI_WIRELESS 0x0056 115#define HCI_WIRELESS 0x0056
116#define HCI_ACCELEROMETER 0x006d
114#define HCI_KBD_ILLUMINATION 0x0095 117#define HCI_KBD_ILLUMINATION 0x0095
115#define HCI_ECO_MODE 0x0097 118#define HCI_ECO_MODE 0x0097
119#define HCI_ACCELEROMETER2 0x00a6
116#define SCI_ILLUMINATION 0x014e 120#define SCI_ILLUMINATION 0x014e
117#define SCI_KBD_ILLUM_STATUS 0x015c 121#define SCI_KBD_ILLUM_STATUS 0x015c
118#define SCI_TOUCHPAD 0x050e 122#define SCI_TOUCHPAD 0x050e
119 123
120/* field definitions */ 124/* field definitions */
125#define HCI_ACCEL_MASK 0x7fff
121#define HCI_HOTKEY_DISABLE 0x0b 126#define HCI_HOTKEY_DISABLE 0x0b
122#define HCI_HOTKEY_ENABLE 0x09 127#define HCI_HOTKEY_ENABLE 0x09
123#define HCI_LCD_BRIGHTNESS_BITS 3 128#define HCI_LCD_BRIGHTNESS_BITS 3
@@ -162,6 +167,7 @@ struct toshiba_acpi_dev {
162 unsigned int kbd_led_registered:1; 167 unsigned int kbd_led_registered:1;
163 unsigned int touchpad_supported:1; 168 unsigned int touchpad_supported:1;
164 unsigned int eco_supported:1; 169 unsigned int eco_supported:1;
170 unsigned int accelerometer_supported:1;
165 unsigned int sysfs_created:1; 171 unsigned int sysfs_created:1;
166 172
167 struct mutex mutex; 173 struct mutex mutex;
@@ -624,6 +630,52 @@ static void toshiba_eco_mode_set_status(struct led_classdev *cdev,
624 return; 630 return;
625 } 631 }
626} 632}
633
634/* Accelerometer support */
635static int toshiba_accelerometer_supported(struct toshiba_acpi_dev *dev)
636{
637 u32 in[HCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER2, 0, 0, 0, 0 };
638 u32 out[HCI_WORDS];
639 acpi_status status;
640
641 /* Check if the accelerometer call exists,
642 * this call also serves as initialization
643 */
644 status = hci_raw(dev, in, out);
645 if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) {
646 pr_err("ACPI call to query the accelerometer failed\n");
647 return -EIO;
648 } else if (out[0] == HCI_DATA_NOT_AVAILABLE ||
649 out[0] == HCI_NOT_INITIALIZED) {
650 pr_err("Accelerometer not initialized\n");
651 return -EIO;
652 } else if (out[0] == HCI_NOT_SUPPORTED) {
653 pr_info("Accelerometer not supported\n");
654 return -ENODEV;
655 }
656
657 return 0;
658}
659
660static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev,
661 u32 *xy, u32 *z)
662{
663 u32 in[HCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER, 0, 1, 0, 0 };
664 u32 out[HCI_WORDS];
665 acpi_status status;
666
667 /* Check the Accelerometer status */
668 status = hci_raw(dev, in, out);
669 if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) {
670 pr_err("ACPI call to query the accelerometer failed\n");
671 return -EIO;
672 }
673
674 *xy = out[2];
675 *z = out[4];
676
677 return 0;
678}
627 679
628/* Bluetooth rfkill handlers */ 680/* Bluetooth rfkill handlers */
629 681
@@ -1257,6 +1309,27 @@ static ssize_t toshiba_touchpad_show(struct device *dev,
1257 1309
1258 return sprintf(buf, "%i\n", state); 1310 return sprintf(buf, "%i\n", state);
1259} 1311}
1312
1313static ssize_t toshiba_position_show(struct device *dev,
1314 struct device_attribute *attr, char *buf)
1315{
1316 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1317 u32 xyval, zval, tmp;
1318 u16 x, y, z;
1319 int ret;
1320
1321 xyval = zval = 0;
1322 ret = toshiba_accelerometer_get(toshiba, &xyval, &zval);
1323 if (ret < 0)
1324 return ret;
1325
1326 x = xyval & HCI_ACCEL_MASK;
1327 tmp = xyval >> HCI_MISC_SHIFT;
1328 y = tmp & HCI_ACCEL_MASK;
1329 z = zval & HCI_ACCEL_MASK;
1330
1331 return sprintf(buf, "%d %d %d\n", x, y, z);
1332}
1260 1333
1261static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR, 1334static DEVICE_ATTR(kbd_backlight_mode, S_IRUGO | S_IWUSR,
1262 toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store); 1335 toshiba_kbd_bl_mode_show, toshiba_kbd_bl_mode_store);
@@ -1264,11 +1337,13 @@ static DEVICE_ATTR(kbd_backlight_timeout, S_IRUGO | S_IWUSR,
1264 toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store); 1337 toshiba_kbd_bl_timeout_show, toshiba_kbd_bl_timeout_store);
1265static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR, 1338static DEVICE_ATTR(touchpad, S_IRUGO | S_IWUSR,
1266 toshiba_touchpad_show, toshiba_touchpad_store); 1339 toshiba_touchpad_show, toshiba_touchpad_store);
1340static DEVICE_ATTR(position, S_IRUGO, toshiba_position_show, NULL);
1267 1341
1268static struct attribute *toshiba_attributes[] = { 1342static struct attribute *toshiba_attributes[] = {
1269 &dev_attr_kbd_backlight_mode.attr, 1343 &dev_attr_kbd_backlight_mode.attr,
1270 &dev_attr_kbd_backlight_timeout.attr, 1344 &dev_attr_kbd_backlight_timeout.attr,
1271 &dev_attr_touchpad.attr, 1345 &dev_attr_touchpad.attr,
1346 &dev_attr_position.attr,
1272 NULL, 1347 NULL,
1273}; 1348};
1274 1349
@@ -1285,6 +1360,8 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
1285 exists = (drv->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false; 1360 exists = (drv->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false;
1286 else if (attr == &dev_attr_touchpad.attr) 1361 else if (attr == &dev_attr_touchpad.attr)
1287 exists = (drv->touchpad_supported) ? true : false; 1362 exists = (drv->touchpad_supported) ? true : false;
1363 else if (attr == &dev_attr_position.attr)
1364 exists = (drv->accelerometer_supported) ? true : false;
1288 1365
1289 return exists ? attr->mode : 0; 1366 return exists ? attr->mode : 0;
1290} 1367}
@@ -1643,6 +1720,9 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
1643 1720
1644 ret = toshiba_touchpad_get(dev, &dummy); 1721 ret = toshiba_touchpad_get(dev, &dummy);
1645 dev->touchpad_supported = !ret; 1722 dev->touchpad_supported = !ret;
1723
1724 ret = toshiba_accelerometer_supported(dev);
1725 dev->accelerometer_supported = !ret;
1646 1726
1647 /* Determine whether or not BIOS supports fan and video interfaces */ 1727 /* Determine whether or not BIOS supports fan and video interfaces */
1648 1728