[media] em28xx: add image quality bridge controls

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>
This commit is contained in:
Frank Schaefer 2013-02-15 14:38:32 -03:00 committed by Mauro Carvalho Chehab
parent 43a5e08d00
commit 8f8b113a03
2 changed files with 57 additions and 8 deletions

View 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;

View 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) {