Commit 8f8b113a authored by Frank Schaefer's avatar Frank Schaefer Committed by Mauro Carvalho Chehab

[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: default avatarFrank Schäfer <fschaefer.oss@googlemail.com>
Acked-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 43a5e08d
...@@ -3091,7 +3091,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, ...@@ -3091,7 +3091,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
return retval; return retval;
} }
v4l2_ctrl_handler_init(hdl, 4); v4l2_ctrl_handler_init(hdl, 8);
dev->v4l2_dev.ctrl_handler = hdl; dev->v4l2_dev.ctrl_handler = hdl;
/* register i2c bus */ /* register i2c bus */
...@@ -3160,11 +3160,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, ...@@ -3160,11 +3160,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
msleep(3); msleep(3);
} }
v4l2_ctrl_handler_setup(&dev->ctrl_handler);
retval = dev->ctrl_handler.error;
if (retval)
goto fail;
retval = em28xx_register_analog_devices(dev); retval = em28xx_register_analog_devices(dev);
if (retval < 0) { if (retval < 0) {
goto fail; goto fail;
......
...@@ -782,17 +782,38 @@ void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv) ...@@ -782,17 +782,38 @@ void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv)
static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl) static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler); struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler);
int ret = -EINVAL;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
dev->mute = ctrl->val; dev->mute = ctrl->val;
ret = em28xx_audio_analog_set(dev);
break; break;
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME:
dev->volume = ctrl->val; 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; break;
} }
return em28xx_audio_analog_set(dev); return (ret < 0) ? ret : 0;
} }
const struct v4l2_ctrl_ops em28xx_ctrl_ops = { const struct v4l2_ctrl_ops em28xx_ctrl_ops = {
...@@ -1784,9 +1805,42 @@ int em28xx_register_analog_devices(struct em28xx *dev) ...@@ -1784,9 +1805,42 @@ int em28xx_register_analog_devices(struct em28xx *dev)
(EM28XX_XCLK_AUDIO_UNMUTE | val)); (EM28XX_XCLK_AUDIO_UNMUTE | val));
em28xx_set_outfmt(dev); em28xx_set_outfmt(dev);
em28xx_colorlevels_set_default(dev);
em28xx_compression_disable(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 */ /* allocate and fill video video_device struct */
dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
if (!dev->vdev) { if (!dev->vdev) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment