diff options
-rw-r--r-- | drivers/input/misc/adxl34x.c | 62 | ||||
-rw-r--r-- | include/linux/input/adxl34x.h | 56 |
2 files changed, 114 insertions, 4 deletions
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 07f9ef631540..77fb40987059 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c | |||
@@ -196,6 +196,8 @@ struct adxl34x { | |||
196 | struct axis_triple hwcal; | 196 | struct axis_triple hwcal; |
197 | struct axis_triple saved; | 197 | struct axis_triple saved; |
198 | char phys[32]; | 198 | char phys[32]; |
199 | unsigned orient2d_saved; | ||
200 | unsigned orient3d_saved; | ||
199 | bool disabled; /* P: mutex */ | 201 | bool disabled; /* P: mutex */ |
200 | bool opened; /* P: mutex */ | 202 | bool opened; /* P: mutex */ |
201 | bool fifo_delay; | 203 | bool fifo_delay; |
@@ -296,7 +298,7 @@ static irqreturn_t adxl34x_irq(int irq, void *handle) | |||
296 | { | 298 | { |
297 | struct adxl34x *ac = handle; | 299 | struct adxl34x *ac = handle; |
298 | struct adxl34x_platform_data *pdata = &ac->pdata; | 300 | struct adxl34x_platform_data *pdata = &ac->pdata; |
299 | int int_stat, tap_stat, samples; | 301 | int int_stat, tap_stat, samples, orient, orient_code; |
300 | 302 | ||
301 | /* | 303 | /* |
302 | * ACT_TAP_STATUS should be read before clearing the interrupt | 304 | * ACT_TAP_STATUS should be read before clearing the interrupt |
@@ -332,6 +334,36 @@ static irqreturn_t adxl34x_irq(int irq, void *handle) | |||
332 | pdata->ev_code_act_inactivity, 0); | 334 | pdata->ev_code_act_inactivity, 0); |
333 | } | 335 | } |
334 | 336 | ||
337 | /* | ||
338 | * ORIENTATION SENSING ADXL346 only | ||
339 | */ | ||
340 | if (pdata->orientation_enable) { | ||
341 | orient = AC_READ(ac, ORIENT); | ||
342 | if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) && | ||
343 | (orient & ADXL346_2D_VALID)) { | ||
344 | |||
345 | orient_code = ADXL346_2D_ORIENT(orient); | ||
346 | /* Report orientation only when it changes */ | ||
347 | if (ac->orient2d_saved != orient_code) { | ||
348 | ac->orient2d_saved = orient_code; | ||
349 | adxl34x_report_key_single(ac->input, | ||
350 | pdata->ev_codes_orient_2d[orient_code]); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) && | ||
355 | (orient & ADXL346_3D_VALID)) { | ||
356 | |||
357 | orient_code = ADXL346_3D_ORIENT(orient) - 1; | ||
358 | /* Report orientation only when it changes */ | ||
359 | if (ac->orient3d_saved != orient_code) { | ||
360 | ac->orient3d_saved = orient_code; | ||
361 | adxl34x_report_key_single(ac->input, | ||
362 | pdata->ev_codes_orient_3d[orient_code]); | ||
363 | } | ||
364 | } | ||
365 | } | ||
366 | |||
335 | if (int_stat & (DATA_READY | WATERMARK)) { | 367 | if (int_stat & (DATA_READY | WATERMARK)) { |
336 | 368 | ||
337 | if (pdata->fifo_mode) | 369 | if (pdata->fifo_mode) |
@@ -641,7 +673,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, | |||
641 | struct adxl34x *ac; | 673 | struct adxl34x *ac; |
642 | struct input_dev *input_dev; | 674 | struct input_dev *input_dev; |
643 | const struct adxl34x_platform_data *pdata; | 675 | const struct adxl34x_platform_data *pdata; |
644 | int err, range; | 676 | int err, range, i; |
645 | unsigned char revid; | 677 | unsigned char revid; |
646 | 678 | ||
647 | if (!irq) { | 679 | if (!irq) { |
@@ -797,12 +829,34 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, | |||
797 | AC_WRITE(ac, FIFO_CTL, FIFO_MODE(pdata->fifo_mode) | | 829 | AC_WRITE(ac, FIFO_CTL, FIFO_MODE(pdata->fifo_mode) | |
798 | SAMPLES(pdata->watermark)); | 830 | SAMPLES(pdata->watermark)); |
799 | 831 | ||
800 | if (pdata->use_int2) | 832 | if (pdata->use_int2) { |
801 | /* Map all INTs to INT2 */ | 833 | /* Map all INTs to INT2 */ |
802 | AC_WRITE(ac, INT_MAP, ac->int_mask | OVERRUN); | 834 | AC_WRITE(ac, INT_MAP, ac->int_mask | OVERRUN); |
803 | else | 835 | } else { |
804 | /* Map all INTs to INT1 */ | 836 | /* Map all INTs to INT1 */ |
805 | AC_WRITE(ac, INT_MAP, 0); | 837 | AC_WRITE(ac, INT_MAP, 0); |
838 | } | ||
839 | |||
840 | if (ac->model == 346 && ac->pdata.orientation_enable) { | ||
841 | AC_WRITE(ac, ORIENT_CONF, | ||
842 | ORIENT_DEADZONE(ac->pdata.deadzone_angle) | | ||
843 | ORIENT_DIVISOR(ac->pdata.divisor_length)); | ||
844 | |||
845 | ac->orient2d_saved = 1234; | ||
846 | ac->orient3d_saved = 1234; | ||
847 | |||
848 | if (pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) | ||
849 | for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_3d); i++) | ||
850 | __set_bit(pdata->ev_codes_orient_3d[i], | ||
851 | input_dev->keybit); | ||
852 | |||
853 | if (pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) | ||
854 | for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_2d); i++) | ||
855 | __set_bit(pdata->ev_codes_orient_2d[i], | ||
856 | input_dev->keybit); | ||
857 | } else { | ||
858 | ac->pdata.orientation_enable = 0; | ||
859 | } | ||
806 | 860 | ||
807 | AC_WRITE(ac, INT_ENABLE, ac->int_mask | OVERRUN); | 861 | AC_WRITE(ac, INT_ENABLE, ac->int_mask | OVERRUN); |
808 | 862 | ||
diff --git a/include/linux/input/adxl34x.h b/include/linux/input/adxl34x.h index 712118238038..df00d998a44a 100644 --- a/include/linux/input/adxl34x.h +++ b/include/linux/input/adxl34x.h | |||
@@ -288,6 +288,62 @@ struct adxl34x_platform_data { | |||
288 | u32 ev_code_ff; /* EV_KEY */ | 288 | u32 ev_code_ff; /* EV_KEY */ |
289 | u32 ev_code_act_inactivity; /* EV_KEY */ | 289 | u32 ev_code_act_inactivity; /* EV_KEY */ |
290 | 290 | ||
291 | /* | ||
292 | * Use ADXL34x INT2 instead of INT1 | ||
293 | */ | ||
291 | u8 use_int2; | 294 | u8 use_int2; |
295 | |||
296 | /* | ||
297 | * ADXL346 only ORIENTATION SENSING feature | ||
298 | * The orientation function of the ADXL346 reports both 2-D and | ||
299 | * 3-D orientation concurrently. | ||
300 | */ | ||
301 | |||
302 | #define ADXL_EN_ORIENTATION_2D 1 | ||
303 | #define ADXL_EN_ORIENTATION_3D 2 | ||
304 | #define ADXL_EN_ORIENTATION_2D_3D 3 | ||
305 | |||
306 | u8 orientation_enable; | ||
307 | |||
308 | /* | ||
309 | * The width of the deadzone region between two or more | ||
310 | * orientation positions is determined by setting the Deadzone | ||
311 | * value. The deadzone region size can be specified with a | ||
312 | * resolution of 3.6deg. The deadzone angle represents the total | ||
313 | * angle where the orientation is considered invalid. | ||
314 | */ | ||
315 | |||
316 | #define ADXL_DEADZONE_ANGLE_0p0 0 /* !!!0.0 [deg] */ | ||
317 | #define ADXL_DEADZONE_ANGLE_3p6 1 /* 3.6 [deg] */ | ||
318 | #define ADXL_DEADZONE_ANGLE_7p2 2 /* 7.2 [deg] */ | ||
319 | #define ADXL_DEADZONE_ANGLE_10p8 3 /* 10.8 [deg] */ | ||
320 | #define ADXL_DEADZONE_ANGLE_14p4 4 /* 14.4 [deg] */ | ||
321 | #define ADXL_DEADZONE_ANGLE_18p0 5 /* 18.0 [deg] */ | ||
322 | #define ADXL_DEADZONE_ANGLE_21p6 6 /* 21.6 [deg] */ | ||
323 | #define ADXL_DEADZONE_ANGLE_25p2 7 /* 25.2 [deg] */ | ||
324 | |||
325 | u8 deadzone_angle; | ||
326 | |||
327 | /* | ||
328 | * To eliminate most human motion such as walking or shaking, | ||
329 | * a Divisor value should be selected to effectively limit the | ||
330 | * orientation bandwidth. Set the depth of the filter used to | ||
331 | * low-pass filter the measured acceleration for stable | ||
332 | * orientation sensing | ||
333 | */ | ||
334 | |||
335 | #define ADXL_LP_FILTER_DIVISOR_2 0 | ||
336 | #define ADXL_LP_FILTER_DIVISOR_4 1 | ||
337 | #define ADXL_LP_FILTER_DIVISOR_8 2 | ||
338 | #define ADXL_LP_FILTER_DIVISOR_16 3 | ||
339 | #define ADXL_LP_FILTER_DIVISOR_32 4 | ||
340 | #define ADXL_LP_FILTER_DIVISOR_64 5 | ||
341 | #define ADXL_LP_FILTER_DIVISOR_128 6 | ||
342 | #define ADXL_LP_FILTER_DIVISOR_256 7 | ||
343 | |||
344 | u8 divisor_length; | ||
345 | |||
346 | u32 ev_codes_orient_2d[4]; /* EV_KEY {+X, -X, +Y, -Y} */ | ||
347 | u32 ev_codes_orient_3d[6]; /* EV_KEY {+Z, +Y, +X, -X, -Y, -Z} */ | ||
292 | }; | 348 | }; |
293 | #endif | 349 | #endif |