aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe Bilotta <giuseppe.bilotta@gmail.com>2009-02-18 17:48:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-02-18 18:37:54 -0500
commit137bad32342a613586347341d1307c2b9812ef44 (patch)
tree3ed900e263388a72f92930a8d91a9d2eb7f0a39b
parentef2cfc790bf5f0ff189b01eabc0f4feb5e8524df (diff)
lis3lv02d: support both one- and two-byte sensors
Sensors responding with 0x3B to WHO_AM_I only have one data register per direction, thus returning a signed byte from the position which is occupied by the MSB in sensors responding with 0x3A. Since multiple sensors share the reply to WHO_AM_I, we rename the defines to better indicate what they identify (family of single and double precision sensors). We support both kind of sensors by checking for the sensor type on init and defining appropriate data-access routines and sensor limits (for the joystick) depending on what we find. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com> Acked-by: Eric Piel <Eric.Piel@tremplin-utc.net> Cc: Pavel Machek <pavel@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/hwmon/hp_accel.c36
-rw-r--r--drivers/hwmon/lis3lv02d.c25
-rw-r--r--drivers/hwmon/lis3lv02d.h16
3 files changed, 51 insertions, 26 deletions
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index dcefe1d2adbd..6b16566c4e6c 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -237,9 +237,25 @@ static void lis3lv02d_enum_resources(struct acpi_device *device)
237 printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); 237 printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
238} 238}
239 239
240static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
241{
242 u8 lo, hi;
243
244 adev.read(handle, reg - 1, &lo);
245 adev.read(handle, reg, &hi);
246 /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
247 return (s16)((hi << 8) | lo);
248}
249
250static s16 lis3lv02d_read_8(acpi_handle handle, int reg)
251{
252 s8 lo;
253 adev.read(handle, reg, &lo);
254 return lo;
255}
256
240static int lis3lv02d_add(struct acpi_device *device) 257static int lis3lv02d_add(struct acpi_device *device)
241{ 258{
242 u8 val;
243 int ret; 259 int ret;
244 260
245 if (!device) 261 if (!device)
@@ -253,10 +269,22 @@ static int lis3lv02d_add(struct acpi_device *device)
253 strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); 269 strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
254 device->driver_data = &adev; 270 device->driver_data = &adev;
255 271
256 lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val); 272 lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami);
257 if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) { 273 switch (adev.whoami) {
274 case LIS_DOUBLE_ID:
275 printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n");
276 adev.read_data = lis3lv02d_read_16;
277 adev.mdps_max_val = 2048;
278 break;
279 case LIS_SINGLE_ID:
280 printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n");
281 adev.read_data = lis3lv02d_read_8;
282 adev.mdps_max_val = 128;
283 break;
284 default:
258 printk(KERN_ERR DRIVER_NAME 285 printk(KERN_ERR DRIVER_NAME
259 ": Accelerometer chip not LIS3LV02D{L,Q}\n"); 286 ": unknown sensor type 0x%X\n", adev.whoami);
287 return -EINVAL;
260 } 288 }
261 289
262 /* If possible use a "standard" axes order */ 290 /* If possible use a "standard" axes order */
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 3afa3afc77f3..8bb2158f0453 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -53,9 +53,6 @@
53 * joystick. 53 * joystick.
54 */ 54 */
55 55
56/* Maximum value our axis may get for the input device (signed 12 bits) */
57#define MDPS_MAX_VAL 2048
58
59struct acpi_lis3lv02d adev = { 56struct acpi_lis3lv02d adev = {
60 .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait), 57 .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait),
61}; 58};
@@ -64,16 +61,6 @@ EXPORT_SYMBOL_GPL(adev);
64 61
65static int lis3lv02d_add_fs(struct acpi_device *device); 62static int lis3lv02d_add_fs(struct acpi_device *device);
66 63
67static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
68{
69 u8 lo, hi;
70
71 adev.read(handle, reg, &lo);
72 adev.read(handle, reg + 1, &hi);
73 /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
74 return (s16)((hi << 8) | lo);
75}
76
77/** 64/**
78 * lis3lv02d_get_axis - For the given axis, give the value converted 65 * lis3lv02d_get_axis - For the given axis, give the value converted
79 * @axis: 1,2,3 - can also be negative 66 * @axis: 1,2,3 - can also be negative
@@ -102,9 +89,9 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
102{ 89{
103 int position[3]; 90 int position[3];
104 91
105 position[0] = lis3lv02d_read_16(handle, OUTX_L); 92 position[0] = adev.read_data(handle, OUTX);
106 position[1] = lis3lv02d_read_16(handle, OUTY_L); 93 position[1] = adev.read_data(handle, OUTY);
107 position[2] = lis3lv02d_read_16(handle, OUTZ_L); 94 position[2] = adev.read_data(handle, OUTZ);
108 95
109 *x = lis3lv02d_get_axis(adev.ac.x, position); 96 *x = lis3lv02d_get_axis(adev.ac.x, position);
110 *y = lis3lv02d_get_axis(adev.ac.y, position); 97 *y = lis3lv02d_get_axis(adev.ac.y, position);
@@ -355,9 +342,9 @@ int lis3lv02d_joystick_enable(void)
355 adev.idev->close = lis3lv02d_joystick_close; 342 adev.idev->close = lis3lv02d_joystick_close;
356 343
357 set_bit(EV_ABS, adev.idev->evbit); 344 set_bit(EV_ABS, adev.idev->evbit);
358 input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); 345 input_set_abs_params(adev.idev, ABS_X, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
359 input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); 346 input_set_abs_params(adev.idev, ABS_Y, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
360 input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); 347 input_set_abs_params(adev.idev, ABS_Z, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
361 348
362 err = input_register_device(adev.idev); 349 err = input_register_device(adev.idev);
363 if (err) { 350 if (err) {
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 2e7597c42d80..75972bf372ff 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -22,12 +22,15 @@
22/* 22/*
23 * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to 23 * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
24 * be connected via SPI. There exists also several similar chips (such as LIS302DL or 24 * be connected via SPI. There exists also several similar chips (such as LIS302DL or
25 * LIS3L02DQ) but not in the HP laptops and they have slightly different registers. 25 * LIS3L02DQ) and they have slightly different registers, but we can provide a
26 * common interface for all of them.
26 * They can also be connected via I²C. 27 * They can also be connected via I²C.
27 */ 28 */
28 29
29#define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */ 30/* 2-byte registers */
30#define LIS302DL_ID 0x3B /* Also the LIS202DL! */ 31#define LIS_DOUBLE_ID 0x3A /* LIS3LV02D[LQ] */
32/* 1-byte registers */
33#define LIS_SINGLE_ID 0x3B /* LIS[32]02DL and others */
31 34
32enum lis3lv02d_reg { 35enum lis3lv02d_reg {
33 WHO_AM_I = 0x0F, 36 WHO_AM_I = 0x0F,
@@ -44,10 +47,13 @@ enum lis3lv02d_reg {
44 STATUS_REG = 0x27, 47 STATUS_REG = 0x27,
45 OUTX_L = 0x28, 48 OUTX_L = 0x28,
46 OUTX_H = 0x29, 49 OUTX_H = 0x29,
50 OUTX = 0x29,
47 OUTY_L = 0x2A, 51 OUTY_L = 0x2A,
48 OUTY_H = 0x2B, 52 OUTY_H = 0x2B,
53 OUTY = 0x2B,
49 OUTZ_L = 0x2C, 54 OUTZ_L = 0x2C,
50 OUTZ_H = 0x2D, 55 OUTZ_H = 0x2D,
56 OUTZ = 0x2D,
51 FF_WU_CFG = 0x30, 57 FF_WU_CFG = 0x30,
52 FF_WU_SRC = 0x31, 58 FF_WU_SRC = 0x31,
53 FF_WU_ACK = 0x32, 59 FF_WU_ACK = 0x32,
@@ -159,6 +165,10 @@ struct acpi_lis3lv02d {
159 acpi_status (*write) (acpi_handle handle, int reg, u8 val); 165 acpi_status (*write) (acpi_handle handle, int reg, u8 val);
160 acpi_status (*read) (acpi_handle handle, int reg, u8 *ret); 166 acpi_status (*read) (acpi_handle handle, int reg, u8 *ret);
161 167
168 u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */
169 s16 (*read_data) (acpi_handle handle, int reg);
170 int mdps_max_val;
171
162 struct input_dev *idev; /* input device */ 172 struct input_dev *idev; /* input device */
163 struct task_struct *kthread; /* kthread for input */ 173 struct task_struct *kthread; /* kthread for input */
164 struct mutex lock; 174 struct mutex lock;