summaryrefslogtreecommitdiffstats
path: root/drivers/media/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/em28xx/em28xx-core.c19
-rw-r--r--drivers/media/usb/em28xx/em28xx-input.c19
-rw-r--r--drivers/media/usb/em28xx/em28xx.h3
3 files changed, 40 insertions, 1 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 4a8179aafc4d..fc8254035278 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -226,6 +226,25 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
EXPORT_SYMBOL_GPL(em28xx_write_reg_bits);
/*
+ * em28xx_toggle_reg_bits()
+ * toggles/inverts the bits (specified by bitmask) of a register
+ */
+int em28xx_toggle_reg_bits(struct em28xx *dev, u16 reg, u8 bitmask)
+{
+ int oldval;
+ u8 newval;
+
+ oldval = em28xx_read_reg(dev, reg);
+ if (oldval < 0)
+ return oldval;
+
+ newval = (~oldval & bitmask) | (oldval & ~bitmask);
+
+ return em28xx_write_reg(dev, reg, newval);
+}
+EXPORT_SYMBOL_GPL(em28xx_toggle_reg_bits);
+
+/*
* em28xx_is_ac97_ready()
* Checks if ac97 is ready
*/
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index ebc538730e07..e0acc92f0dfd 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -480,6 +480,7 @@ static void em28xx_query_buttons(struct work_struct *work)
u8 i, j;
int regval;
bool is_pressed, was_pressed;
+ const struct em28xx_led *led;
/* Poll and evaluate all addresses */
for (i = 0; i < dev->num_button_polling_addresses; i++) {
@@ -524,6 +525,15 @@ static void em28xx_query_buttons(struct work_struct *work)
input_report_key(dev->sbutton_input_dev,
EM28XX_SNAPSHOT_KEY, 0);
break;
+ case EM28XX_BUTTON_ILLUMINATION:
+ led = em28xx_find_led(dev,
+ EM28XX_LED_ILLUMINATION);
+ /* Switch illumination LED on/off */
+ if (led)
+ em28xx_toggle_reg_bits(dev,
+ led->gpio_reg,
+ led->gpio_mask);
+ break;
default:
WARN_ONCE(1, "BUG: unhandled button role.");
}
@@ -600,10 +610,17 @@ static void em28xx_init_buttons(struct em28xx *dev)
WARN_ONCE(1, "BUG: maximum number of button polling addresses exceeded.");
addr_new = 0;
}
- /* Register input device (if needed) */
+ /* Button role specific checks and actions */
if (button->role == EM28XX_BUTTON_SNAPSHOT) {
+ /* Register input device */
if (em28xx_register_snapshot_button(dev) < 0)
addr_new = 0;
+ } else if (button->role == EM28XX_BUTTON_ILLUMINATION) {
+ /* Check sanity */
+ if (!em28xx_find_led(dev, EM28XX_LED_ILLUMINATION)) {
+ em28xx_errdev("BUG: illumination button defined, but no illumination LED.\n");
+ addr_new = 0;
+ }
}
/* Add read address to list of polling addresses */
if (addr_new) {
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index f60f236a245f..43e29683eb6a 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -379,6 +379,7 @@ enum em28xx_adecoder {
enum em28xx_led_role {
EM28XX_LED_ANALOG_CAPTURING = 0,
+ EM28XX_LED_ILLUMINATION,
EM28XX_NUM_LED_ROLES, /* must be the last */
};
@@ -391,6 +392,7 @@ struct em28xx_led {
enum em28xx_button_role {
EM28XX_BUTTON_SNAPSHOT = 0,
+ EM28XX_BUTTON_ILLUMINATION,
EM28XX_NUM_BUTTON_ROLES, /* must be the last */
};
@@ -709,6 +711,7 @@ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val);
int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
u8 bitmask);
+int em28xx_toggle_reg_bits(struct em28xx *dev, u16 reg, u8 bitmask);
int em28xx_read_ac97(struct em28xx *dev, u8 reg);
int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val);