diff options
Diffstat (limited to 'drivers/hwmon/lis3lv02d.c')
-rw-r--r-- | drivers/hwmon/lis3lv02d.c | 86 |
1 files changed, 57 insertions, 29 deletions
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index eeae7c9600e4..778eb7795983 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/freezer.h> | 36 | #include <linux/freezer.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
39 | #include <acpi/acpi_drivers.h> | ||
40 | #include <asm/atomic.h> | 39 | #include <asm/atomic.h> |
41 | #include "lis3lv02d.h" | 40 | #include "lis3lv02d.h" |
42 | 41 | ||
@@ -53,18 +52,27 @@ | |||
53 | * joystick. | 52 | * joystick. |
54 | */ | 53 | */ |
55 | 54 | ||
56 | struct acpi_lis3lv02d lis3_dev = { | 55 | struct lis3lv02d lis3_dev = { |
57 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait), | 56 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait), |
58 | }; | 57 | }; |
59 | 58 | ||
60 | EXPORT_SYMBOL_GPL(lis3_dev); | 59 | EXPORT_SYMBOL_GPL(lis3_dev); |
61 | 60 | ||
62 | static s16 lis3lv02d_read_16(acpi_handle handle, int reg) | 61 | static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg) |
62 | { | ||
63 | s8 lo; | ||
64 | if (lis3->read(lis3, reg, &lo) < 0) | ||
65 | return 0; | ||
66 | |||
67 | return lo; | ||
68 | } | ||
69 | |||
70 | static s16 lis3lv02d_read_16(struct lis3lv02d *lis3, int reg) | ||
63 | { | 71 | { |
64 | u8 lo, hi; | 72 | u8 lo, hi; |
65 | 73 | ||
66 | lis3_dev.read(handle, reg, &lo); | 74 | lis3->read(lis3, reg - 1, &lo); |
67 | lis3_dev.read(handle, reg + 1, &hi); | 75 | lis3->read(lis3, reg, &hi); |
68 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | 76 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ |
69 | return (s16)((hi << 8) | lo); | 77 | return (s16)((hi << 8) | lo); |
70 | } | 78 | } |
@@ -86,36 +94,36 @@ static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3]) | |||
86 | 94 | ||
87 | /** | 95 | /** |
88 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer | 96 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer |
89 | * @handle: the handle to the device | 97 | * @lis3: pointer to the device struct |
90 | * @x: where to store the X axis value | 98 | * @x: where to store the X axis value |
91 | * @y: where to store the Y axis value | 99 | * @y: where to store the Y axis value |
92 | * @z: where to store the Z axis value | 100 | * @z: where to store the Z axis value |
93 | * | 101 | * |
94 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ | 102 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ |
95 | */ | 103 | */ |
96 | static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) | 104 | static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) |
97 | { | 105 | { |
98 | int position[3]; | 106 | int position[3]; |
99 | 107 | ||
100 | position[0] = lis3_dev.read_data(handle, OUTX); | 108 | position[0] = lis3_dev.read_data(lis3, OUTX); |
101 | position[1] = lis3_dev.read_data(handle, OUTY); | 109 | position[1] = lis3_dev.read_data(lis3, OUTY); |
102 | position[2] = lis3_dev.read_data(handle, OUTZ); | 110 | position[2] = lis3_dev.read_data(lis3, OUTZ); |
103 | 111 | ||
104 | *x = lis3lv02d_get_axis(lis3_dev.ac.x, position); | 112 | *x = lis3lv02d_get_axis(lis3_dev.ac.x, position); |
105 | *y = lis3lv02d_get_axis(lis3_dev.ac.y, position); | 113 | *y = lis3lv02d_get_axis(lis3_dev.ac.y, position); |
106 | *z = lis3lv02d_get_axis(lis3_dev.ac.z, position); | 114 | *z = lis3lv02d_get_axis(lis3_dev.ac.z, position); |
107 | } | 115 | } |
108 | 116 | ||
109 | void lis3lv02d_poweroff(acpi_handle handle) | 117 | void lis3lv02d_poweroff(struct lis3lv02d *lis3) |
110 | { | 118 | { |
111 | lis3_dev.is_on = 0; | 119 | lis3_dev.is_on = 0; |
112 | } | 120 | } |
113 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); | 121 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); |
114 | 122 | ||
115 | void lis3lv02d_poweron(acpi_handle handle) | 123 | void lis3lv02d_poweron(struct lis3lv02d *lis3) |
116 | { | 124 | { |
117 | lis3_dev.is_on = 1; | 125 | lis3_dev.is_on = 1; |
118 | lis3_dev.init(handle); | 126 | lis3_dev.init(lis3); |
119 | } | 127 | } |
120 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | 128 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); |
121 | 129 | ||
@@ -124,13 +132,13 @@ EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | |||
124 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be | 132 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be |
125 | * used from interrupt context. | 133 | * used from interrupt context. |
126 | */ | 134 | */ |
127 | static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | 135 | static void lis3lv02d_increase_use(struct lis3lv02d *dev) |
128 | { | 136 | { |
129 | mutex_lock(&dev->lock); | 137 | mutex_lock(&dev->lock); |
130 | dev->usage++; | 138 | dev->usage++; |
131 | if (dev->usage == 1) { | 139 | if (dev->usage == 1) { |
132 | if (!dev->is_on) | 140 | if (!dev->is_on) |
133 | lis3lv02d_poweron(dev->device->handle); | 141 | lis3lv02d_poweron(dev); |
134 | } | 142 | } |
135 | mutex_unlock(&dev->lock); | 143 | mutex_unlock(&dev->lock); |
136 | } | 144 | } |
@@ -139,12 +147,12 @@ static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | |||
139 | * To be called whenever a usage of the device is stopped. | 147 | * To be called whenever a usage of the device is stopped. |
140 | * It will make sure to turn off the device when there is not usage. | 148 | * It will make sure to turn off the device when there is not usage. |
141 | */ | 149 | */ |
142 | static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev) | 150 | static void lis3lv02d_decrease_use(struct lis3lv02d *dev) |
143 | { | 151 | { |
144 | mutex_lock(&dev->lock); | 152 | mutex_lock(&dev->lock); |
145 | dev->usage--; | 153 | dev->usage--; |
146 | if (dev->usage == 0) | 154 | if (dev->usage == 0) |
147 | lis3lv02d_poweroff(dev->device->handle); | 155 | lis3lv02d_poweroff(dev); |
148 | mutex_unlock(&dev->lock); | 156 | mutex_unlock(&dev->lock); |
149 | } | 157 | } |
150 | 158 | ||
@@ -291,7 +299,7 @@ static int lis3lv02d_joystick_kthread(void *data) | |||
291 | int x, y, z; | 299 | int x, y, z; |
292 | 300 | ||
293 | while (!kthread_should_stop()) { | 301 | while (!kthread_should_stop()) { |
294 | lis3lv02d_get_xyz(lis3_dev.device->handle, &x, &y, &z); | 302 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
295 | input_report_abs(lis3_dev.idev, ABS_X, x - lis3_dev.xcalib); | 303 | input_report_abs(lis3_dev.idev, ABS_X, x - lis3_dev.xcalib); |
296 | input_report_abs(lis3_dev.idev, ABS_Y, y - lis3_dev.ycalib); | 304 | input_report_abs(lis3_dev.idev, ABS_Y, y - lis3_dev.ycalib); |
297 | input_report_abs(lis3_dev.idev, ABS_Z, z - lis3_dev.zcalib); | 305 | input_report_abs(lis3_dev.idev, ABS_Z, z - lis3_dev.zcalib); |
@@ -325,7 +333,8 @@ static void lis3lv02d_joystick_close(struct input_dev *input) | |||
325 | 333 | ||
326 | static inline void lis3lv02d_calibrate_joystick(void) | 334 | static inline void lis3lv02d_calibrate_joystick(void) |
327 | { | 335 | { |
328 | lis3lv02d_get_xyz(lis3_dev.device->handle, &lis3_dev.xcalib, &lis3_dev.ycalib, &lis3_dev.zcalib); | 336 | lis3lv02d_get_xyz(&lis3_dev, |
337 | &lis3_dev.xcalib, &lis3_dev.ycalib, &lis3_dev.zcalib); | ||
329 | } | 338 | } |
330 | 339 | ||
331 | int lis3lv02d_joystick_enable(void) | 340 | int lis3lv02d_joystick_enable(void) |
@@ -382,7 +391,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev, | |||
382 | int x, y, z; | 391 | int x, y, z; |
383 | 392 | ||
384 | lis3lv02d_increase_use(&lis3_dev); | 393 | lis3lv02d_increase_use(&lis3_dev); |
385 | lis3lv02d_get_xyz(lis3_dev.device->handle, &x, &y, &z); | 394 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
386 | lis3lv02d_decrease_use(&lis3_dev); | 395 | lis3lv02d_decrease_use(&lis3_dev); |
387 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | 396 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); |
388 | } | 397 | } |
@@ -412,7 +421,7 @@ static ssize_t lis3lv02d_rate_show(struct device *dev, | |||
412 | int val; | 421 | int val; |
413 | 422 | ||
414 | lis3lv02d_increase_use(&lis3_dev); | 423 | lis3lv02d_increase_use(&lis3_dev); |
415 | lis3_dev.read(lis3_dev.device->handle, CTRL_REG1, &ctrl); | 424 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); |
416 | lis3lv02d_decrease_use(&lis3_dev); | 425 | lis3lv02d_decrease_use(&lis3_dev); |
417 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; | 426 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; |
418 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); | 427 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); |
@@ -435,7 +444,7 @@ static struct attribute_group lis3lv02d_attribute_group = { | |||
435 | }; | 444 | }; |
436 | 445 | ||
437 | 446 | ||
438 | static int lis3lv02d_add_fs(struct acpi_device *device) | 447 | static int lis3lv02d_add_fs(struct lis3lv02d *lis3) |
439 | { | 448 | { |
440 | lis3_dev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | 449 | lis3_dev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); |
441 | if (IS_ERR(lis3_dev.pdev)) | 450 | if (IS_ERR(lis3_dev.pdev)) |
@@ -456,10 +465,29 @@ EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); | |||
456 | * Initialise the accelerometer and the various subsystems. | 465 | * Initialise the accelerometer and the various subsystems. |
457 | * Should be rather independant of the bus system. | 466 | * Should be rather independant of the bus system. |
458 | */ | 467 | */ |
459 | int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) | 468 | int lis3lv02d_init_device(struct lis3lv02d *dev) |
460 | { | 469 | { |
470 | dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I); | ||
471 | |||
472 | switch (dev->whoami) { | ||
473 | case LIS_DOUBLE_ID: | ||
474 | printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); | ||
475 | dev->read_data = lis3lv02d_read_16; | ||
476 | dev->mdps_max_val = 2048; | ||
477 | break; | ||
478 | case LIS_SINGLE_ID: | ||
479 | printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); | ||
480 | dev->read_data = lis3lv02d_read_8; | ||
481 | dev->mdps_max_val = 128; | ||
482 | break; | ||
483 | default: | ||
484 | printk(KERN_ERR DRIVER_NAME | ||
485 | ": unknown sensor type 0x%X\n", lis3_dev.whoami); | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
461 | mutex_init(&dev->lock); | 489 | mutex_init(&dev->lock); |
462 | lis3lv02d_add_fs(dev->device); | 490 | lis3lv02d_add_fs(dev); |
463 | lis3lv02d_increase_use(dev); | 491 | lis3lv02d_increase_use(dev); |
464 | 492 | ||
465 | if (lis3lv02d_joystick_enable()) | 493 | if (lis3lv02d_joystick_enable()) |
@@ -467,10 +495,10 @@ int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) | |||
467 | 495 | ||
468 | printk("lis3_init_device: irq %d\n", dev->irq); | 496 | printk("lis3_init_device: irq %d\n", dev->irq); |
469 | 497 | ||
470 | /* if we did not get an IRQ from ACPI - we have nothing more to do */ | 498 | /* bail if we did not get an IRQ from the bus layer */ |
471 | if (!dev->irq) { | 499 | if (!dev->irq) { |
472 | printk(KERN_ERR DRIVER_NAME | 500 | printk(KERN_ERR DRIVER_NAME |
473 | ": No IRQ in ACPI. Disabling /dev/freefall\n"); | 501 | ": No IRQ. Disabling /dev/freefall\n"); |
474 | goto out; | 502 | goto out; |
475 | } | 503 | } |
476 | 504 | ||