[media] em28xx: add image quality bridge controls
authorFrank Schaefer <fschaefer.oss@googlemail.com>
Fri, 15 Feb 2013 17:38:32 +0000 (14:38 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 4 Mar 2013 17:51:30 +0000 (14:51 -0300)
Add the image quality bridge controls contrast, brightness, saturation,
blue balance, red balance and sharpness.
These controls are enabled only if no subdevice provides them.
Tested with the following devices:
"Terratec Cinergy 200 USB"
"Hauppauge HVR-900"
"SilverCrest 1.3MPix webcam"
"Hauppauge WinTV USB2"
"Speedlink VAD Laplace webcam"

Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/usb/em28xx/em28xx-cards.c
drivers/media/usb/em28xx/em28xx-video.c

index 54a03b20de6e9a8b680413d4a136fcf1804da7a2..9332d051bde9bad55e0453fc81ee89762184dc77 100644 (file)
@@ -3091,7 +3091,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
                return retval;
        }
 
-       v4l2_ctrl_handler_init(hdl, 4);
+       v4l2_ctrl_handler_init(hdl, 8);
        dev->v4l2_dev.ctrl_handler = hdl;
 
        /* register i2c bus */
@@ -3160,11 +3160,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
                msleep(3);
        }
 
-       v4l2_ctrl_handler_setup(&dev->ctrl_handler);
-       retval = dev->ctrl_handler.error;
-       if (retval)
-               goto fail;
-
        retval = em28xx_register_analog_devices(dev);
        if (retval < 0) {
                goto fail;
index 86fd90727f56dca6e595d36b297d6e085948f946..48b937d1b063ff786783f69cb4a24367e0a8c09c 100644 (file)
@@ -782,17 +782,38 @@ void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
 static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler);
+       int ret = -EINVAL;
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
                dev->mute = ctrl->val;
+               ret = em28xx_audio_analog_set(dev);
                break;
        case V4L2_CID_AUDIO_VOLUME:
                dev->volume = ctrl->val;
+               ret = em28xx_audio_analog_set(dev);
+               break;
+       case V4L2_CID_CONTRAST:
+               ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val);
+               break;
+       case V4L2_CID_BRIGHTNESS:
+               ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val);
                break;
        }
 
-       return em28xx_audio_analog_set(dev);
+       return (ret < 0) ? ret : 0;
 }
 
 const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
@@ -1784,9 +1805,42 @@ int em28xx_register_analog_devices(struct em28xx *dev)
                         (EM28XX_XCLK_AUDIO_UNMUTE | val));
 
        em28xx_set_outfmt(dev);
-       em28xx_colorlevels_set_default(dev);
        em28xx_compression_disable(dev);
 
+       /* Add image controls */
+       /* NOTE: at this point, the subdevices are already registered, so bridge
+        * controls are only added/enabled when no subdevice provides them */
+       if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_CONTRAST))
+               v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+                                 V4L2_CID_CONTRAST,
+                                 0, 0x1f, 1, CONTRAST_DEFAULT);
+       if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BRIGHTNESS))
+               v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+                                 V4L2_CID_BRIGHTNESS,
+                                 -0x80, 0x7f, 1, BRIGHTNESS_DEFAULT);
+       if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SATURATION))
+               v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+                                 V4L2_CID_SATURATION,
+                                 0, 0x1f, 1, SATURATION_DEFAULT);
+       if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_BLUE_BALANCE))
+               v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+                                 V4L2_CID_BLUE_BALANCE,
+                                 -0x30, 0x30, 1, BLUE_BALANCE_DEFAULT);
+       if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_RED_BALANCE))
+               v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+                                 V4L2_CID_RED_BALANCE,
+                                 -0x30, 0x30, 1, RED_BALANCE_DEFAULT);
+       if (NULL == v4l2_ctrl_find(&dev->ctrl_handler, V4L2_CID_SHARPNESS))
+               v4l2_ctrl_new_std(&dev->ctrl_handler, &em28xx_ctrl_ops,
+                                 V4L2_CID_SHARPNESS,
+                                 0, 0x0f, 1, SHARPNESS_DEFAULT);
+
+       /* Reset image controls */
+       em28xx_colorlevels_set_default(dev);
+       v4l2_ctrl_handler_setup(&dev->ctrl_handler);
+       if (dev->ctrl_handler.error)
+               return dev->ctrl_handler.error;
+
        /* allocate and fill video video_device struct */
        dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
        if (!dev->vdev) {