Commit 9f747359 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] tm6000: convert to the control framework

Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 2c2a0536
...@@ -63,71 +63,6 @@ static bool keep_urb; /* keep urb buffers allocated */ ...@@ -63,71 +63,6 @@ static bool keep_urb; /* keep urb buffers allocated */
int tm6000_debug; int tm6000_debug;
EXPORT_SYMBOL_GPL(tm6000_debug); EXPORT_SYMBOL_GPL(tm6000_debug);
static const struct v4l2_queryctrl no_ctrl = {
.name = "42",
.flags = V4L2_CTRL_FLAG_DISABLED,
};
/* supported controls */
static struct v4l2_queryctrl tm6000_qctrl[] = {
{
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
.maximum = 255,
.step = 1,
.default_value = 54,
.flags = 0,
}, {
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
.maximum = 255,
.step = 0x1,
.default_value = 119,
.flags = 0,
}, {
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Saturation",
.minimum = 0,
.maximum = 255,
.step = 0x1,
.default_value = 112,
.flags = 0,
}, {
.id = V4L2_CID_HUE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Hue",
.minimum = -128,
.maximum = 127,
.step = 0x1,
.default_value = 0,
.flags = 0,
},
/* --- audio --- */
{
.id = V4L2_CID_AUDIO_MUTE,
.name = "Mute",
.minimum = 0,
.maximum = 1,
.type = V4L2_CTRL_TYPE_BOOLEAN,
}, {
.id = V4L2_CID_AUDIO_VOLUME,
.name = "Volume",
.minimum = -15,
.maximum = 15,
.step = 1,
.default_value = 0,
.type = V4L2_CTRL_TYPE_INTEGER,
}
};
static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
static struct tm6000_fmt format[] = { static struct tm6000_fmt format[] = {
{ {
.name = "4:2:2, packed, YVY2", .name = "4:2:2, packed, YVY2",
...@@ -144,16 +79,6 @@ static struct tm6000_fmt format[] = { ...@@ -144,16 +79,6 @@ static struct tm6000_fmt format[] = {
} }
}; };
static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
{
unsigned int i;
for (i = 0; i < CTRLS; i++)
if (tm6000_qctrl[i].id == id)
return tm6000_qctrl+i;
return NULL;
}
/* ------------------------------------------------------------------ /* ------------------------------------------------------------------
* DMA and thread functions * DMA and thread functions
* ------------------------------------------------------------------ * ------------------------------------------------------------------
...@@ -1215,79 +1140,40 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) ...@@ -1215,79 +1140,40 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
} }
/* --- controls ---------------------------------------------- */ /* --- controls ---------------------------------------------- */
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
int i;
for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) static int tm6000_s_ctrl(struct v4l2_ctrl *ctrl)
if (qc->id && qc->id == tm6000_qctrl[i].id) {
memcpy(qc, &(tm6000_qctrl[i]),
sizeof(*qc));
return 0;
}
return -EINVAL;
}
static int vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{ {
struct tm6000_fh *fh = priv; struct tm6000_core *dev = container_of(ctrl->handler, struct tm6000_core, ctrl_handler);
struct tm6000_core *dev = fh->dev; u8 val = ctrl->val;
int val;
/* FIXME: Probably, those won't work! Maybe we need shadow regs */
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_CONTRAST: case V4L2_CID_CONTRAST:
val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0); tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
break; return 0;
case V4L2_CID_BRIGHTNESS: case V4L2_CID_BRIGHTNESS:
val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0); tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
return 0; return 0;
case V4L2_CID_SATURATION: case V4L2_CID_SATURATION:
val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0); tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
return 0; return 0;
case V4L2_CID_HUE: case V4L2_CID_HUE:
val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0); tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
return 0;
case V4L2_CID_AUDIO_MUTE:
val = dev->ctl_mute;
return 0;
case V4L2_CID_AUDIO_VOLUME:
val = dev->ctl_volume;
return 0; return 0;
default:
return -EINVAL;
} }
return -EINVAL;
}
if (val < 0) static const struct v4l2_ctrl_ops tm6000_ctrl_ops = {
return val; .s_ctrl = tm6000_s_ctrl,
};
ctrl->value = val;
return 0; static int tm6000_radio_s_ctrl(struct v4l2_ctrl *ctrl)
}
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{ {
struct tm6000_fh *fh = priv; struct tm6000_core *dev = container_of(ctrl->handler,
struct tm6000_core *dev = fh->dev; struct tm6000_core, radio_ctrl_handler);
u8 val = ctrl->value; u8 val = ctrl->val;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_CONTRAST:
tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
return 0;
case V4L2_CID_BRIGHTNESS:
tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
return 0;
case V4L2_CID_SATURATION:
tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
return 0;
case V4L2_CID_HUE:
tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
return 0;
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
dev->ctl_mute = val; dev->ctl_mute = val;
tm6000_tvaudio_set_mute(dev, val); tm6000_tvaudio_set_mute(dev, val);
...@@ -1300,6 +1186,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv, ...@@ -1300,6 +1186,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
} }
static const struct v4l2_ctrl_ops tm6000_radio_ctrl_ops = {
.s_ctrl = tm6000_radio_s_ctrl,
};
static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t) struct v4l2_tuner *t)
{ {
...@@ -1418,23 +1308,6 @@ static int radio_s_tuner(struct file *file, void *priv, ...@@ -1418,23 +1308,6 @@ static int radio_s_tuner(struct file *file, void *priv,
return 0; return 0;
} }
static int radio_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *c)
{
const struct v4l2_queryctrl *ctrl;
if (c->id < V4L2_CID_BASE ||
c->id >= V4L2_CID_LASTP1)
return -EINVAL;
if (c->id == V4L2_CID_AUDIO_MUTE) {
ctrl = ctrl_by_id(c->id);
*c = *ctrl;
} else
*c = no_ctrl;
return 0;
}
/* ------------------------------------------------------------------ /* ------------------------------------------------------------------
File operations for the device File operations for the device
------------------------------------------------------------------*/ ------------------------------------------------------------------*/
...@@ -1445,7 +1318,7 @@ static int __tm6000_open(struct file *file) ...@@ -1445,7 +1318,7 @@ static int __tm6000_open(struct file *file)
struct tm6000_core *dev = video_drvdata(file); struct tm6000_core *dev = video_drvdata(file);
struct tm6000_fh *fh; struct tm6000_fh *fh;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
int i, rc; int rc;
int radio = 0; int radio = 0;
dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n", dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
...@@ -1505,13 +1378,7 @@ static int __tm6000_open(struct file *file) ...@@ -1505,13 +1378,7 @@ static int __tm6000_open(struct file *file)
if (rc < 0) if (rc < 0)
return rc; return rc;
if (dev->mode != TM6000_MODE_ANALOG) {
/* Put all controls at a sane state */
for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
qctl_regs[i] = tm6000_qctrl[i].default_value;
dev->mode = TM6000_MODE_ANALOG; dev->mode = TM6000_MODE_ANALOG;
}
if (!fh->radio) { if (!fh->radio) {
videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops, videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
...@@ -1678,9 +1545,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { ...@@ -1678,9 +1545,6 @@ static const struct v4l2_ioctl_ops video_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_g_tuner = vidioc_g_tuner, .vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner, .vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency, .vidioc_g_frequency = vidioc_g_frequency,
...@@ -1713,9 +1577,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { ...@@ -1713,9 +1577,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
.vidioc_querycap = vidioc_querycap, .vidioc_querycap = vidioc_querycap,
.vidioc_g_tuner = radio_g_tuner, .vidioc_g_tuner = radio_g_tuner,
.vidioc_s_tuner = radio_s_tuner, .vidioc_s_tuner = radio_s_tuner,
.vidioc_queryctrl = radio_queryctrl,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_g_frequency = vidioc_g_frequency, .vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency, .vidioc_s_frequency = vidioc_s_frequency,
}; };
...@@ -1755,15 +1616,41 @@ static struct video_device *vdev_init(struct tm6000_core *dev, ...@@ -1755,15 +1616,41 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
int tm6000_v4l2_register(struct tm6000_core *dev) int tm6000_v4l2_register(struct tm6000_core *dev)
{ {
int ret = -1; int ret = 0;
v4l2_ctrl_handler_init(&dev->ctrl_handler, 6);
v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 2);
v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops,
V4L2_CID_AUDIO_VOLUME, -15, 15, 1, 0);
v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 255, 1, 54);
v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
V4L2_CID_CONTRAST, 0, 255, 1, 119);
v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
V4L2_CID_SATURATION, 0, 255, 1, 112);
v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
V4L2_CID_HUE, -128, 127, 1, 0);
v4l2_ctrl_add_handler(&dev->ctrl_handler,
&dev->radio_ctrl_handler, NULL);
if (dev->radio_ctrl_handler.error)
ret = dev->radio_ctrl_handler.error;
if (!ret && dev->ctrl_handler.error)
ret = dev->ctrl_handler.error;
if (ret)
goto free_ctrl;
dev->vfd = vdev_init(dev, &tm6000_template, "video"); dev->vfd = vdev_init(dev, &tm6000_template, "video");
if (!dev->vfd) { if (!dev->vfd) {
printk(KERN_INFO "%s: can't register video device\n", printk(KERN_INFO "%s: can't register video device\n",
dev->name); dev->name);
return -ENOMEM; ret = -ENOMEM;
goto free_ctrl;
} }
dev->vfd->ctrl_handler = &dev->ctrl_handler;
/* init video dma queues */ /* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.active);
...@@ -1774,7 +1661,9 @@ int tm6000_v4l2_register(struct tm6000_core *dev) ...@@ -1774,7 +1661,9 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
if (ret < 0) { if (ret < 0) {
printk(KERN_INFO "%s: can't register video device\n", printk(KERN_INFO "%s: can't register video device\n",
dev->name); dev->name);
return ret; video_device_release(dev->vfd);
dev->vfd = NULL;
goto free_ctrl;
} }
printk(KERN_INFO "%s: registered device %s\n", printk(KERN_INFO "%s: registered device %s\n",
...@@ -1787,15 +1676,17 @@ int tm6000_v4l2_register(struct tm6000_core *dev) ...@@ -1787,15 +1676,17 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
printk(KERN_INFO "%s: can't register radio device\n", printk(KERN_INFO "%s: can't register radio device\n",
dev->name); dev->name);
ret = -ENXIO; ret = -ENXIO;
return ret; /* FIXME release resource */ goto unreg_video;
} }
dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
radio_nr); radio_nr);
if (ret < 0) { if (ret < 0) {
printk(KERN_INFO "%s: can't register radio device\n", printk(KERN_INFO "%s: can't register radio device\n",
dev->name); dev->name);
return ret; /* FIXME release resource */ video_device_release(dev->radio_dev);
goto unreg_video;
} }
printk(KERN_INFO "%s: registered device %s\n", printk(KERN_INFO "%s: registered device %s\n",
...@@ -1804,6 +1695,13 @@ int tm6000_v4l2_register(struct tm6000_core *dev) ...@@ -1804,6 +1695,13 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
return ret; return ret;
unreg_video:
video_unregister_device(dev->vfd);
free_ctrl:
v4l2_ctrl_handler_free(&dev->ctrl_handler);
v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
return ret;
} }
int tm6000_v4l2_unregister(struct tm6000_core *dev) int tm6000_v4l2_unregister(struct tm6000_core *dev)
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
#include "dvb_demux.h" #include "dvb_demux.h"
...@@ -222,6 +223,8 @@ struct tm6000_core { ...@@ -222,6 +223,8 @@ struct tm6000_core {
struct video_device *radio_dev; struct video_device *radio_dev;
struct tm6000_dmaqueue vidq; struct tm6000_dmaqueue vidq;
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_ctrl_handler radio_ctrl_handler;
int input; int input;
struct tm6000_input vinput[3]; /* video input */ struct tm6000_input vinput[3]; /* video input */
......
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