summaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/em28xx/em28xx-input.c
diff options
context:
space:
mode:
authorFrank Schaefer <fschaefer.oss@googlemail.com>2013-12-01 18:06:53 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-12-10 16:11:28 -0200
commit7763481a97488f201e7b6a42ddce1d163cd6297a (patch)
treefa3c54c3b84d418cd60959fbb951e54a3871a4ba /drivers/media/usb/em28xx/em28xx-input.c
parentf522260993822d82e2c480aa676aa4ca1230d235 (diff)
downloadlinux-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.c30
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,