From 671386bb23c57e5448f386a41101ed65ad1d488c Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 25 Jun 2010 08:44:10 -0700 Subject: Input: adxl34x - add support for ADXL346 orientation sensing Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Signed-off-by: Dmitry Torokhov --- drivers/input/misc/adxl34x.c | 62 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'drivers/input') 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 { struct axis_triple hwcal; struct axis_triple saved; char phys[32]; + unsigned orient2d_saved; + unsigned orient3d_saved; bool disabled; /* P: mutex */ bool opened; /* P: mutex */ bool fifo_delay; @@ -296,7 +298,7 @@ static irqreturn_t adxl34x_irq(int irq, void *handle) { struct adxl34x *ac = handle; struct adxl34x_platform_data *pdata = &ac->pdata; - int int_stat, tap_stat, samples; + int int_stat, tap_stat, samples, orient, orient_code; /* * ACT_TAP_STATUS should be read before clearing the interrupt @@ -332,6 +334,36 @@ static irqreturn_t adxl34x_irq(int irq, void *handle) pdata->ev_code_act_inactivity, 0); } + /* + * ORIENTATION SENSING ADXL346 only + */ + if (pdata->orientation_enable) { + orient = AC_READ(ac, ORIENT); + if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) && + (orient & ADXL346_2D_VALID)) { + + orient_code = ADXL346_2D_ORIENT(orient); + /* Report orientation only when it changes */ + if (ac->orient2d_saved != orient_code) { + ac->orient2d_saved = orient_code; + adxl34x_report_key_single(ac->input, + pdata->ev_codes_orient_2d[orient_code]); + } + } + + if ((pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) && + (orient & ADXL346_3D_VALID)) { + + orient_code = ADXL346_3D_ORIENT(orient) - 1; + /* Report orientation only when it changes */ + if (ac->orient3d_saved != orient_code) { + ac->orient3d_saved = orient_code; + adxl34x_report_key_single(ac->input, + pdata->ev_codes_orient_3d[orient_code]); + } + } + } + if (int_stat & (DATA_READY | WATERMARK)) { if (pdata->fifo_mode) @@ -641,7 +673,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, struct adxl34x *ac; struct input_dev *input_dev; const struct adxl34x_platform_data *pdata; - int err, range; + int err, range, i; unsigned char revid; if (!irq) { @@ -797,12 +829,34 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, AC_WRITE(ac, FIFO_CTL, FIFO_MODE(pdata->fifo_mode) | SAMPLES(pdata->watermark)); - if (pdata->use_int2) + if (pdata->use_int2) { /* Map all INTs to INT2 */ AC_WRITE(ac, INT_MAP, ac->int_mask | OVERRUN); - else + } else { /* Map all INTs to INT1 */ AC_WRITE(ac, INT_MAP, 0); + } + + if (ac->model == 346 && ac->pdata.orientation_enable) { + AC_WRITE(ac, ORIENT_CONF, + ORIENT_DEADZONE(ac->pdata.deadzone_angle) | + ORIENT_DIVISOR(ac->pdata.divisor_length)); + + ac->orient2d_saved = 1234; + ac->orient3d_saved = 1234; + + if (pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) + for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_3d); i++) + __set_bit(pdata->ev_codes_orient_3d[i], + input_dev->keybit); + + if (pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) + for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_2d); i++) + __set_bit(pdata->ev_codes_orient_2d[i], + input_dev->keybit); + } else { + ac->pdata.orientation_enable = 0; + } AC_WRITE(ac, INT_ENABLE, ac->int_mask | OVERRUN); -- cgit v1.2.3