[media] em28xx: add support for GPO controlled analog capturing LEDs
authorFrank Schaefer <fschaefer.oss@googlemail.com>
Sun, 1 Dec 2013 21:06:51 +0000 (18:06 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Tue, 10 Dec 2013 18:08:40 +0000 (16:08 -0200)
Some devices are equipped with a capturing status LED that needs to be
switched on/off explicitly via a GPO port.

Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/usb/em28xx/em28xx-core.c
drivers/media/usb/em28xx/em28xx.h

index fc157af5234a3e2c82c83dbd3f6d498758b96589..31d6ab2555f2dc25e9da2d3b2be66a997e29b59f 100644 (file)
@@ -608,46 +608,51 @@ int em28xx_capture_start(struct em28xx *dev, int start)
            dev->chip_id == CHIP_ID_EM2884 ||
            dev->chip_id == CHIP_ID_EM28174) {
                /* The Transport Stream Enable Register moved in em2874 */
-               if (!start) {
-                       rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
-                                                  0x00,
-                                                  EM2874_TS1_CAPTURE_ENABLE);
-                       return rc;
-               }
-
-               /* Enable Transport Stream */
                rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
-                                          EM2874_TS1_CAPTURE_ENABLE,
+                                          start ?
+                                              EM2874_TS1_CAPTURE_ENABLE : 0x00,
                                           EM2874_TS1_CAPTURE_ENABLE);
-               return rc;
-       }
-
+       } else {
+               /* FIXME: which is the best order? */
+               /* video registers are sampled by VREF */
+               rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
+                                          start ? 0x10 : 0x00, 0x10);
+               if (rc < 0)
+                       return rc;
 
-       /* FIXME: which is the best order? */
-       /* video registers are sampled by VREF */
-       rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
-                                  start ? 0x10 : 0x00, 0x10);
-       if (rc < 0)
-               return rc;
+               if (start) {
+                       if (dev->board.is_webcam)
+                               rc = em28xx_write_reg(dev, 0x13, 0x0c);
 
-       if (!start) {
-               /* disable video capture */
-               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27);
-               return rc;
-       }
+                       /* Enable video capture */
+                       rc = em28xx_write_reg(dev, 0x48, 0x00);
 
-       if (dev->board.is_webcam)
-               rc = em28xx_write_reg(dev, 0x13, 0x0c);
+                       if (dev->mode == EM28XX_ANALOG_MODE)
+                               rc = em28xx_write_reg(dev,
+                                                   EM28XX_R12_VINENABLE, 0x67);
+                       else
+                               rc = em28xx_write_reg(dev,
+                                                   EM28XX_R12_VINENABLE, 0x37);
 
-       /* enable video capture */
-       rc = em28xx_write_reg(dev, 0x48, 0x00);
+                       msleep(6);
+               } else {
+                       /* disable video capture */
+                       rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27);
+               }
+       }
 
-       if (dev->mode == EM28XX_ANALOG_MODE)
-               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
-       else
-               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
+       if (rc < 0)
+               return rc;
 
-       msleep(6);
+       /* Switch (explicitly controlled) analog capturing LED on/off */
+       if ((dev->mode == EM28XX_ANALOG_MODE)
+           && dev->board.analog_capturing_led) {
+               struct em28xx_led *led = dev->board.analog_capturing_led;
+               em28xx_write_reg_bits(dev, led->gpio_reg,
+                                     (!start ^ led->inverted) ?
+                                     ~led->gpio_mask : led->gpio_mask,
+                                     led->gpio_mask);
+       }
 
        return rc;
 }
index f8726ad5d0a8776063c6acbc482c9180ee10b08c..8003c2f7bb96005e897d59a0d62e970238ef3e18 100644 (file)
@@ -374,6 +374,12 @@ enum em28xx_adecoder {
        EM28XX_TVAUDIO,
 };
 
+struct em28xx_led {
+       u8 gpio_reg;
+       u8 gpio_mask;
+       bool inverted;
+};
+
 struct em28xx_board {
        char *name;
        int vchannels;
@@ -410,6 +416,9 @@ struct em28xx_board {
        struct em28xx_input       input[MAX_EM28XX_INPUT];
        struct em28xx_input       radio;
        char                      *ir_codes;
+
+       /* LEDs that need to be controlled explicitly */
+       struct em28xx_led         *analog_capturing_led;
 };
 
 struct em28xx_eeprom {