aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/lis3lv02d.c98
-rw-r--r--drivers/hwmon/lis3lv02d.h1
-rw-r--r--include/linux/lis3lv02d.h2
3 files changed, 88 insertions, 13 deletions
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 3c06350bae3a..56a1d34d3670 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -121,11 +121,9 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
121 int position[3]; 121 int position[3];
122 int i; 122 int i;
123 123
124 mutex_lock(&lis3->mutex);
125 position[0] = lis3->read_data(lis3, OUTX); 124 position[0] = lis3->read_data(lis3, OUTX);
126 position[1] = lis3->read_data(lis3, OUTY); 125 position[1] = lis3->read_data(lis3, OUTY);
127 position[2] = lis3->read_data(lis3, OUTZ); 126 position[2] = lis3->read_data(lis3, OUTZ);
128 mutex_unlock(&lis3->mutex);
129 127
130 for (i = 0; i < 3; i++) 128 for (i = 0; i < 3; i++)
131 position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY; 129 position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
@@ -249,6 +247,19 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
249EXPORT_SYMBOL_GPL(lis3lv02d_poweron); 247EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
250 248
251 249
250static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
251{
252 int x, y, z;
253
254 mutex_lock(&lis3_dev.mutex);
255 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
256 input_report_abs(pidev->input, ABS_X, x);
257 input_report_abs(pidev->input, ABS_Y, y);
258 input_report_abs(pidev->input, ABS_Z, z);
259 input_sync(pidev->input);
260 mutex_unlock(&lis3_dev.mutex);
261}
262
252static irqreturn_t lis302dl_interrupt(int irq, void *dummy) 263static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
253{ 264{
254 if (!test_bit(0, &lis3_dev.misc_opened)) 265 if (!test_bit(0, &lis3_dev.misc_opened))
@@ -270,13 +281,71 @@ out:
270 return IRQ_HANDLED; 281 return IRQ_HANDLED;
271} 282}
272 283
284static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
285{
286 struct input_dev *dev = lis3->idev->input;
287 u8 click_src;
288
289 mutex_lock(&lis3->mutex);
290 lis3->read(lis3, CLICK_SRC, &click_src);
291
292 if (click_src & CLICK_SINGLE_X) {
293 input_report_key(dev, lis3->mapped_btns[0], 1);
294 input_report_key(dev, lis3->mapped_btns[0], 0);
295 }
296
297 if (click_src & CLICK_SINGLE_Y) {
298 input_report_key(dev, lis3->mapped_btns[1], 1);
299 input_report_key(dev, lis3->mapped_btns[1], 0);
300 }
301
302 if (click_src & CLICK_SINGLE_Z) {
303 input_report_key(dev, lis3->mapped_btns[2], 1);
304 input_report_key(dev, lis3->mapped_btns[2], 0);
305 }
306 input_sync(dev);
307 mutex_unlock(&lis3->mutex);
308}
309
310static void lis302dl_interrupt_handle_ff_wu(struct lis3lv02d *lis3)
311{
312 u8 wu1_src;
313 u8 wu2_src;
314
315 lis3->read(lis3, FF_WU_SRC_1, &wu1_src);
316 lis3->read(lis3, FF_WU_SRC_2, &wu2_src);
317
318 wu1_src = wu1_src & FF_WU_SRC_IA ? wu1_src : 0;
319 wu2_src = wu2_src & FF_WU_SRC_IA ? wu2_src : 0;
320
321 /* joystick poll is internally protected by the lis3->mutex. */
322 if (wu1_src || wu2_src)
323 lis3lv02d_joystick_poll(lis3_dev.idev);
324}
325
273static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data) 326static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
274{ 327{
328
329 struct lis3lv02d *lis3 = data;
330
331 if ((lis3->pdata->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
332 lis302dl_interrupt_handle_click(lis3);
333 else
334 lis302dl_interrupt_handle_ff_wu(lis3);
335
275 return IRQ_HANDLED; 336 return IRQ_HANDLED;
276} 337}
277 338
278static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data) 339static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
279{ 340{
341
342 struct lis3lv02d *lis3 = data;
343
344 if ((lis3->pdata->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
345 lis302dl_interrupt_handle_click(lis3);
346 else
347 lis302dl_interrupt_handle_ff_wu(lis3);
348
280 return IRQ_HANDLED; 349 return IRQ_HANDLED;
281} 350}
282 351
@@ -374,22 +443,12 @@ static struct miscdevice lis3lv02d_misc_device = {
374 .fops = &lis3lv02d_misc_fops, 443 .fops = &lis3lv02d_misc_fops,
375}; 444};
376 445
377static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
378{
379 int x, y, z;
380
381 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
382 input_report_abs(pidev->input, ABS_X, x);
383 input_report_abs(pidev->input, ABS_Y, y);
384 input_report_abs(pidev->input, ABS_Z, z);
385 input_sync(pidev->input);
386}
387
388int lis3lv02d_joystick_enable(void) 446int lis3lv02d_joystick_enable(void)
389{ 447{
390 struct input_dev *input_dev; 448 struct input_dev *input_dev;
391 int err; 449 int err;
392 int max_val, fuzz, flat; 450 int max_val, fuzz, flat;
451 int btns[] = {BTN_X, BTN_Y, BTN_Z};
393 452
394 if (lis3_dev.idev) 453 if (lis3_dev.idev)
395 return -EINVAL; 454 return -EINVAL;
@@ -416,6 +475,10 @@ int lis3lv02d_joystick_enable(void)
416 input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat); 475 input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
417 input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat); 476 input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
418 477
478 lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
479 lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
480 lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
481
419 err = input_register_polled_device(lis3_dev.idev); 482 err = input_register_polled_device(lis3_dev.idev);
420 if (err) { 483 if (err) {
421 input_free_polled_device(lis3_dev.idev); 484 input_free_polled_device(lis3_dev.idev);
@@ -461,7 +524,9 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
461{ 524{
462 int x, y, z; 525 int x, y, z;
463 526
527 mutex_lock(&lis3_dev.mutex);
464 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); 528 lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
529 mutex_unlock(&lis3_dev.mutex);
465 return sprintf(buf, "(%d,%d,%d)\n", x, y, z); 530 return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
466} 531}
467 532
@@ -535,6 +600,13 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
535 dev->write(dev, CLICK_THSY_X, 600 dev->write(dev, CLICK_THSY_X,
536 (p->click_thresh_x & 0xf) | 601 (p->click_thresh_x & 0xf) |
537 (p->click_thresh_y << 4)); 602 (p->click_thresh_y << 4));
603
604 if (dev->idev) {
605 struct input_dev *input_dev = lis3_dev.idev->input;
606 input_set_capability(input_dev, EV_KEY, BTN_X);
607 input_set_capability(input_dev, EV_KEY, BTN_Y);
608 input_set_capability(input_dev, EV_KEY, BTN_Z);
609 }
538 } 610 }
539 611
540 if (p->wakeup_flags) { 612 if (p->wakeup_flags) {
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 692e2442ce08..854091380e33 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -233,6 +233,7 @@ struct lis3lv02d {
233 struct platform_device *pdev; /* platform device */ 233 struct platform_device *pdev; /* platform device */
234 atomic_t count; /* interrupt count after last read */ 234 atomic_t count; /* interrupt count after last read */
235 struct axis_conversion ac; /* hw -> logical axis */ 235 struct axis_conversion ac; /* hw -> logical axis */
236 int mapped_btns[3];
236 237
237 u32 irq; /* IRQ number */ 238 u32 irq; /* IRQ number */
238 struct fasync_struct *async_queue; /* queue for the misc device */ 239 struct fasync_struct *async_queue; /* queue for the misc device */
diff --git a/include/linux/lis3lv02d.h b/include/linux/lis3lv02d.h
index fd289b1e1ec1..0e8a346424bb 100644
--- a/include/linux/lis3lv02d.h
+++ b/include/linux/lis3lv02d.h
@@ -25,12 +25,14 @@ struct lis3lv02d_platform_data {
25#define LIS3_IRQ1_FF_WU_12 (3 << 0) 25#define LIS3_IRQ1_FF_WU_12 (3 << 0)
26#define LIS3_IRQ1_DATA_READY (4 << 0) 26#define LIS3_IRQ1_DATA_READY (4 << 0)
27#define LIS3_IRQ1_CLICK (7 << 0) 27#define LIS3_IRQ1_CLICK (7 << 0)
28#define LIS3_IRQ1_MASK (7 << 0)
28#define LIS3_IRQ2_DISABLE (0 << 3) 29#define LIS3_IRQ2_DISABLE (0 << 3)
29#define LIS3_IRQ2_FF_WU_1 (1 << 3) 30#define LIS3_IRQ2_FF_WU_1 (1 << 3)
30#define LIS3_IRQ2_FF_WU_2 (2 << 3) 31#define LIS3_IRQ2_FF_WU_2 (2 << 3)
31#define LIS3_IRQ2_FF_WU_12 (3 << 3) 32#define LIS3_IRQ2_FF_WU_12 (3 << 3)
32#define LIS3_IRQ2_DATA_READY (4 << 3) 33#define LIS3_IRQ2_DATA_READY (4 << 3)
33#define LIS3_IRQ2_CLICK (7 << 3) 34#define LIS3_IRQ2_CLICK (7 << 3)
35#define LIS3_IRQ2_MASK (7 << 3)
34#define LIS3_IRQ_OPEN_DRAIN (1 << 6) 36#define LIS3_IRQ_OPEN_DRAIN (1 << 6)
35#define LIS3_IRQ_ACTIVE_LOW (1 << 7) 37#define LIS3_IRQ_ACTIVE_LOW (1 << 7)
36 unsigned char irq_cfg; 38 unsigned char irq_cfg;