aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/misc/adxl34x.c62
-rw-r--r--include/linux/input/adxl34x.h56
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