[media] s2255: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
4ca286610f
commit
192f1e78cb
@ -47,6 +47,7 @@
|
|||||||
#include <media/v4l2-common.h>
|
#include <media/v4l2-common.h>
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
|
#include <media/v4l2-ctrls.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
|
|
||||||
@ -217,6 +218,7 @@ struct s2255_dev;
|
|||||||
|
|
||||||
struct s2255_channel {
|
struct s2255_channel {
|
||||||
struct video_device vdev;
|
struct video_device vdev;
|
||||||
|
struct v4l2_ctrl_handler hdl;
|
||||||
int resources;
|
int resources;
|
||||||
struct s2255_dmaqueue vidq;
|
struct s2255_dmaqueue vidq;
|
||||||
struct s2255_bufferi buffer;
|
struct s2255_bufferi buffer;
|
||||||
@ -336,7 +338,7 @@ struct s2255_fh {
|
|||||||
*/
|
*/
|
||||||
#define S2255_V4L2_YC_ON 1
|
#define S2255_V4L2_YC_ON 1
|
||||||
#define S2255_V4L2_YC_OFF 0
|
#define S2255_V4L2_YC_OFF 0
|
||||||
#define V4L2_CID_PRIVATE_COLORFILTER (V4L2_CID_PRIVATE_BASE + 0)
|
#define V4L2_CID_S2255_COLORFILTER (V4L2_CID_USER_S2255_BASE + 0)
|
||||||
|
|
||||||
/* frame prefix size (sent once every frame) */
|
/* frame prefix size (sent once every frame) */
|
||||||
#define PREFIX_SIZE 512
|
#define PREFIX_SIZE 512
|
||||||
@ -810,28 +812,6 @@ static void res_free(struct s2255_fh *fh)
|
|||||||
dprintk(1, "res: put\n");
|
dprintk(1, "res: put\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_querymenu(struct file *file, void *priv,
|
|
||||||
struct v4l2_querymenu *qmenu)
|
|
||||||
{
|
|
||||||
static const char *colorfilter[] = {
|
|
||||||
"Off",
|
|
||||||
"On",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
if (qmenu->id == V4L2_CID_PRIVATE_COLORFILTER) {
|
|
||||||
int i;
|
|
||||||
const char **menu_items = colorfilter;
|
|
||||||
for (i = 0; i < qmenu->index && menu_items[i]; i++)
|
|
||||||
; /* do nothing (from v4l2-common.c) */
|
|
||||||
if (menu_items[i] == NULL || menu_items[i][0] == '\0')
|
|
||||||
return -EINVAL;
|
|
||||||
strlcpy(qmenu->name, menu_items[qmenu->index],
|
|
||||||
sizeof(qmenu->name));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_querycap(struct file *file, void *priv,
|
static int vidioc_querycap(struct file *file, void *priv,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
@ -1427,109 +1407,32 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- controls ---------------------------------------------- */
|
static int s2255_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
static int vidioc_queryctrl(struct file *file, void *priv,
|
|
||||||
struct v4l2_queryctrl *qc)
|
|
||||||
{
|
{
|
||||||
struct s2255_fh *fh = priv;
|
struct s2255_channel *channel =
|
||||||
struct s2255_channel *channel = fh->channel;
|
container_of(ctrl->handler, struct s2255_channel, hdl);
|
||||||
struct s2255_dev *dev = fh->dev;
|
|
||||||
switch (qc->id) {
|
|
||||||
case V4L2_CID_BRIGHTNESS:
|
|
||||||
v4l2_ctrl_query_fill(qc, -127, 127, 1, DEF_BRIGHT);
|
|
||||||
break;
|
|
||||||
case V4L2_CID_CONTRAST:
|
|
||||||
v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_CONTRAST);
|
|
||||||
break;
|
|
||||||
case V4L2_CID_SATURATION:
|
|
||||||
v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_SATURATION);
|
|
||||||
break;
|
|
||||||
case V4L2_CID_HUE:
|
|
||||||
v4l2_ctrl_query_fill(qc, 0, 255, 1, DEF_HUE);
|
|
||||||
break;
|
|
||||||
case V4L2_CID_PRIVATE_COLORFILTER:
|
|
||||||
if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
|
|
||||||
return -EINVAL;
|
|
||||||
if ((dev->pid == 0x2257) && (channel->idx > 1))
|
|
||||||
return -EINVAL;
|
|
||||||
strlcpy(qc->name, "Color Filter", sizeof(qc->name));
|
|
||||||
qc->type = V4L2_CTRL_TYPE_MENU;
|
|
||||||
qc->minimum = 0;
|
|
||||||
qc->maximum = 1;
|
|
||||||
qc->step = 1;
|
|
||||||
qc->default_value = 1;
|
|
||||||
qc->flags = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
dprintk(4, "%s, id %d\n", __func__, qc->id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_g_ctrl(struct file *file, void *priv,
|
|
||||||
struct v4l2_control *ctrl)
|
|
||||||
{
|
|
||||||
struct s2255_fh *fh = priv;
|
|
||||||
struct s2255_dev *dev = fh->dev;
|
|
||||||
struct s2255_channel *channel = fh->channel;
|
|
||||||
switch (ctrl->id) {
|
|
||||||
case V4L2_CID_BRIGHTNESS:
|
|
||||||
ctrl->value = channel->mode.bright;
|
|
||||||
break;
|
|
||||||
case V4L2_CID_CONTRAST:
|
|
||||||
ctrl->value = channel->mode.contrast;
|
|
||||||
break;
|
|
||||||
case V4L2_CID_SATURATION:
|
|
||||||
ctrl->value = channel->mode.saturation;
|
|
||||||
break;
|
|
||||||
case V4L2_CID_HUE:
|
|
||||||
ctrl->value = channel->mode.hue;
|
|
||||||
break;
|
|
||||||
case V4L2_CID_PRIVATE_COLORFILTER:
|
|
||||||
if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
|
|
||||||
return -EINVAL;
|
|
||||||
if ((dev->pid == 0x2257) && (channel->idx > 1))
|
|
||||||
return -EINVAL;
|
|
||||||
ctrl->value = !((channel->mode.color & MASK_INPUT_TYPE) >> 16);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
dprintk(4, "%s, id %d val %d\n", __func__, ctrl->id, ctrl->value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_s_ctrl(struct file *file, void *priv,
|
|
||||||
struct v4l2_control *ctrl)
|
|
||||||
{
|
|
||||||
struct s2255_fh *fh = priv;
|
|
||||||
struct s2255_channel *channel = fh->channel;
|
|
||||||
struct s2255_dev *dev = to_s2255_dev(channel->vdev.v4l2_dev);
|
|
||||||
struct s2255_mode mode;
|
struct s2255_mode mode;
|
||||||
|
|
||||||
mode = channel->mode;
|
mode = channel->mode;
|
||||||
dprintk(4, "%s\n", __func__);
|
dprintk(4, "%s\n", __func__);
|
||||||
|
|
||||||
/* update the mode to the corresponding value */
|
/* update the mode to the corresponding value */
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case V4L2_CID_BRIGHTNESS:
|
case V4L2_CID_BRIGHTNESS:
|
||||||
mode.bright = ctrl->value;
|
mode.bright = ctrl->val;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_CONTRAST:
|
case V4L2_CID_CONTRAST:
|
||||||
mode.contrast = ctrl->value;
|
mode.contrast = ctrl->val;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_HUE:
|
case V4L2_CID_HUE:
|
||||||
mode.hue = ctrl->value;
|
mode.hue = ctrl->val;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_SATURATION:
|
case V4L2_CID_SATURATION:
|
||||||
mode.saturation = ctrl->value;
|
mode.saturation = ctrl->val;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_PRIVATE_COLORFILTER:
|
case V4L2_CID_S2255_COLORFILTER:
|
||||||
if (dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER)
|
|
||||||
return -EINVAL;
|
|
||||||
if ((dev->pid == 0x2257) && (channel->idx > 1))
|
|
||||||
return -EINVAL;
|
|
||||||
mode.color &= ~MASK_INPUT_TYPE;
|
mode.color &= ~MASK_INPUT_TYPE;
|
||||||
mode.color |= ((ctrl->value ? 0 : 1) << 16);
|
mode.color |= !ctrl->val << 16;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1539,7 +1442,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
|
|||||||
some V4L programs restart stream unnecessarily
|
some V4L programs restart stream unnecessarily
|
||||||
after a s_crtl.
|
after a s_crtl.
|
||||||
*/
|
*/
|
||||||
s2255_set_mode(fh->channel, &mode);
|
s2255_set_mode(channel, &mode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1886,7 +1789,6 @@ static const struct v4l2_file_operations s2255_fops_v4l = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
|
static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
|
||||||
.vidioc_querymenu = vidioc_querymenu,
|
|
||||||
.vidioc_querycap = vidioc_querycap,
|
.vidioc_querycap = vidioc_querycap,
|
||||||
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
|
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
|
||||||
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
|
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
|
||||||
@ -1900,9 +1802,6 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
|
|||||||
.vidioc_enum_input = vidioc_enum_input,
|
.vidioc_enum_input = vidioc_enum_input,
|
||||||
.vidioc_g_input = vidioc_g_input,
|
.vidioc_g_input = vidioc_g_input,
|
||||||
.vidioc_s_input = vidioc_s_input,
|
.vidioc_s_input = vidioc_s_input,
|
||||||
.vidioc_queryctrl = vidioc_queryctrl,
|
|
||||||
.vidioc_g_ctrl = vidioc_g_ctrl,
|
|
||||||
.vidioc_s_ctrl = vidioc_s_ctrl,
|
|
||||||
.vidioc_streamon = vidioc_streamon,
|
.vidioc_streamon = vidioc_streamon,
|
||||||
.vidioc_streamoff = vidioc_streamoff,
|
.vidioc_streamoff = vidioc_streamoff,
|
||||||
.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
|
.vidioc_s_jpegcomp = vidioc_s_jpegcomp,
|
||||||
@ -1915,8 +1814,13 @@ static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
|
|||||||
static void s2255_video_device_release(struct video_device *vdev)
|
static void s2255_video_device_release(struct video_device *vdev)
|
||||||
{
|
{
|
||||||
struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
|
struct s2255_dev *dev = to_s2255_dev(vdev->v4l2_dev);
|
||||||
dprintk(4, "%s, chnls: %d \n", __func__,
|
struct s2255_channel *channel =
|
||||||
|
container_of(vdev, struct s2255_channel, vdev);
|
||||||
|
|
||||||
|
v4l2_ctrl_handler_free(&channel->hdl);
|
||||||
|
dprintk(4, "%s, chnls: %d\n", __func__,
|
||||||
atomic_read(&dev->num_channels));
|
atomic_read(&dev->num_channels));
|
||||||
|
|
||||||
if (atomic_dec_and_test(&dev->num_channels))
|
if (atomic_dec_and_test(&dev->num_channels))
|
||||||
s2255_destroy(dev);
|
s2255_destroy(dev);
|
||||||
return;
|
return;
|
||||||
@ -1931,6 +1835,20 @@ static struct video_device template = {
|
|||||||
.current_norm = V4L2_STD_NTSC_M,
|
.current_norm = V4L2_STD_NTSC_M,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct v4l2_ctrl_ops s2255_ctrl_ops = {
|
||||||
|
.s_ctrl = s2255_s_ctrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct v4l2_ctrl_config color_filter_ctrl = {
|
||||||
|
.ops = &s2255_ctrl_ops,
|
||||||
|
.name = "Color Filter",
|
||||||
|
.id = V4L2_CID_S2255_COLORFILTER,
|
||||||
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||||
|
.max = 1,
|
||||||
|
.step = 1,
|
||||||
|
.def = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static int s2255_probe_v4l(struct s2255_dev *dev)
|
static int s2255_probe_v4l(struct s2255_dev *dev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -1945,9 +1863,29 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
|
|||||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||||
channel = &dev->channel[i];
|
channel = &dev->channel[i];
|
||||||
INIT_LIST_HEAD(&channel->vidq.active);
|
INIT_LIST_HEAD(&channel->vidq.active);
|
||||||
|
|
||||||
|
v4l2_ctrl_handler_init(&channel->hdl, 5);
|
||||||
|
v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
|
||||||
|
V4L2_CID_BRIGHTNESS, -127, 127, 1, DEF_BRIGHT);
|
||||||
|
v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
|
||||||
|
V4L2_CID_CONTRAST, 0, 255, 1, DEF_CONTRAST);
|
||||||
|
v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
|
||||||
|
V4L2_CID_SATURATION, 0, 255, 1, DEF_SATURATION);
|
||||||
|
v4l2_ctrl_new_std(&channel->hdl, &s2255_ctrl_ops,
|
||||||
|
V4L2_CID_HUE, 0, 255, 1, DEF_HUE);
|
||||||
|
if (dev->dsp_fw_ver >= S2255_MIN_DSP_COLORFILTER &&
|
||||||
|
(dev->pid != 0x2257 || channel->idx <= 1))
|
||||||
|
v4l2_ctrl_new_custom(&channel->hdl, &color_filter_ctrl, NULL);
|
||||||
|
if (channel->hdl.error) {
|
||||||
|
ret = channel->hdl.error;
|
||||||
|
v4l2_ctrl_handler_free(&channel->hdl);
|
||||||
|
dev_err(&dev->udev->dev, "couldn't register control\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
channel->vidq.dev = dev;
|
channel->vidq.dev = dev;
|
||||||
/* register 4 video devices */
|
/* register 4 video devices */
|
||||||
channel->vdev = template;
|
channel->vdev = template;
|
||||||
|
channel->vdev.ctrl_handler = &channel->hdl;
|
||||||
channel->vdev.lock = &dev->lock;
|
channel->vdev.lock = &dev->lock;
|
||||||
channel->vdev.v4l2_dev = &dev->v4l2_dev;
|
channel->vdev.v4l2_dev = &dev->v4l2_dev;
|
||||||
video_set_drvdata(&channel->vdev, channel);
|
video_set_drvdata(&channel->vdev, channel);
|
||||||
|
@ -151,6 +151,10 @@ enum v4l2_colorfx {
|
|||||||
#define V4L2_CID_USER_BTTV_BASE (V4L2_CID_USER_BASE + 0x1010)
|
#define V4L2_CID_USER_BTTV_BASE (V4L2_CID_USER_BASE + 0x1010)
|
||||||
|
|
||||||
|
|
||||||
|
/* The base for the s2255 driver controls.
|
||||||
|
* We reserve 8 controls for this driver. */
|
||||||
|
#define V4L2_CID_USER_S2255_BASE (V4L2_CID_USER_BASE + 0x1010)
|
||||||
|
|
||||||
/* MPEG-class control IDs */
|
/* MPEG-class control IDs */
|
||||||
|
|
||||||
#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
|
#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user