diff options
author | Frank Schaefer <fschaefer.oss@googlemail.com> | 2013-12-01 18:06:53 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-12-10 16:11:28 -0200 |
commit | 7763481a97488f201e7b6a42ddce1d163cd6297a (patch) | |
tree | fa3c54c3b84d418cd60959fbb951e54a3871a4ba /drivers/media/usb/em28xx/em28xx-input.c | |
parent | f522260993822d82e2c480aa676aa4ca1230d235 (diff) | |
download | linux-7763481a97488f201e7b6a42ddce1d163cd6297a.tar.bz2 |
[media] em28xx: add debouncing mechanism for GPI-connected buttons
So far, the driver only supports a snapshot button which is assigned to
register 0x0c bit 5. This special port has a built-in debouncing mechanism.
For buttons connected to ordinary GPI ports, this patch implements a software
debouncing mechanism.
Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-input.c')
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-input.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 20c6a8ae1462..ebc538730e07 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -479,7 +479,7 @@ static void em28xx_query_buttons(struct work_struct *work) container_of(work, struct em28xx, buttons_query_work.work); u8 i, j; int regval; - bool pressed; + bool is_pressed, was_pressed; /* Poll and evaluate all addresses */ for (i = 0; i < dev->num_button_polling_addresses; i++) { @@ -497,12 +497,21 @@ static void em28xx_query_buttons(struct work_struct *work) j++; continue; } - /* Determine if button is pressed */ - pressed = regval & button->mask; - if (button->inverted) - pressed = !pressed; + /* Determine if button is and was pressed last time */ + is_pressed = regval & button->mask; + was_pressed = dev->button_polling_last_values[i] + & button->mask; + if (button->inverted) { + is_pressed = !is_pressed; + was_pressed = !was_pressed; + } + /* Clear button state (if needed) */ + if (is_pressed && button->reg_clearing) + em28xx_write_reg(dev, button->reg_clearing, + (~regval & button->mask) + | (regval & ~button->mask)); /* Handle button state */ - if (!pressed) { + if (!is_pressed || was_pressed) { j++; continue; } @@ -518,14 +527,11 @@ static void em28xx_query_buttons(struct work_struct *work) default: WARN_ONCE(1, "BUG: unhandled button role."); } - /* Clear button state (if needed) */ - if (button->reg_clearing) - em28xx_write_reg(dev, button->reg_clearing, - (~regval & button->mask) - | (regval & ~button->mask)); /* Next button */ j++; } + /* Save current value for comparison during the next polling */ + dev->button_polling_last_values[i] = regval; } /* Schedule next poll */ schedule_delayed_work(&dev->buttons_query_work, @@ -611,6 +617,8 @@ static void em28xx_init_buttons(struct em28xx *dev) /* Start polling */ if (dev->num_button_polling_addresses) { + memset(dev->button_polling_last_values, 0, + EM28XX_NUM_BUTTON_ADDRESSES_MAX); INIT_DELAYED_WORK(&dev->buttons_query_work, em28xx_query_buttons); schedule_delayed_work(&dev->buttons_query_work, |