aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2013-01-31 06:23:01 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-02-05 15:30:43 -0500
commit9f7473592bd2c8d73657dcc1644de4ab610b0d90 (patch)
treee5cbdc6fee127b844dc217d2465bcfdca743d3fc /drivers
parent2c2a053626cb712d6006cb10f2760a6018a65631 (diff)
[media] tm6000: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c232
-rw-r--r--drivers/media/usb/tm6000/tm6000.h3
2 files changed, 68 insertions, 167 deletions
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index 7a653b263678..4329fbcf2de2 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -63,71 +63,6 @@ static bool keep_urb; /* keep urb buffers allocated */
63int tm6000_debug; 63int tm6000_debug;
64EXPORT_SYMBOL_GPL(tm6000_debug); 64EXPORT_SYMBOL_GPL(tm6000_debug);
65 65
66static const struct v4l2_queryctrl no_ctrl = {
67 .name = "42",
68 .flags = V4L2_CTRL_FLAG_DISABLED,
69};
70
71/* supported controls */
72static struct v4l2_queryctrl tm6000_qctrl[] = {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 255,
79 .step = 1,
80 .default_value = 54,
81 .flags = 0,
82 }, {
83 .id = V4L2_CID_CONTRAST,
84 .type = V4L2_CTRL_TYPE_INTEGER,
85 .name = "Contrast",
86 .minimum = 0,
87 .maximum = 255,
88 .step = 0x1,
89 .default_value = 119,
90 .flags = 0,
91 }, {
92 .id = V4L2_CID_SATURATION,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Saturation",
95 .minimum = 0,
96 .maximum = 255,
97 .step = 0x1,
98 .default_value = 112,
99 .flags = 0,
100 }, {
101 .id = V4L2_CID_HUE,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Hue",
104 .minimum = -128,
105 .maximum = 127,
106 .step = 0x1,
107 .default_value = 0,
108 .flags = 0,
109 },
110 /* --- audio --- */
111 {
112 .id = V4L2_CID_AUDIO_MUTE,
113 .name = "Mute",
114 .minimum = 0,
115 .maximum = 1,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 }, {
118 .id = V4L2_CID_AUDIO_VOLUME,
119 .name = "Volume",
120 .minimum = -15,
121 .maximum = 15,
122 .step = 1,
123 .default_value = 0,
124 .type = V4L2_CTRL_TYPE_INTEGER,
125 }
126};
127
128static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
129static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
130
131static struct tm6000_fmt format[] = { 66static struct tm6000_fmt format[] = {
132 { 67 {
133 .name = "4:2:2, packed, YVY2", 68 .name = "4:2:2, packed, YVY2",
@@ -144,16 +79,6 @@ static struct tm6000_fmt format[] = {
144 } 79 }
145}; 80};
146 81
147static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
148{
149 unsigned int i;
150
151 for (i = 0; i < CTRLS; i++)
152 if (tm6000_qctrl[i].id == id)
153 return tm6000_qctrl+i;
154 return NULL;
155}
156
157/* ------------------------------------------------------------------ 82/* ------------------------------------------------------------------
158 * DMA and thread functions 83 * DMA and thread functions
159 * ------------------------------------------------------------------ 84 * ------------------------------------------------------------------
@@ -1215,79 +1140,40 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1215} 1140}
1216 1141
1217/* --- controls ---------------------------------------------- */ 1142/* --- controls ---------------------------------------------- */
1218static int vidioc_queryctrl(struct file *file, void *priv,
1219 struct v4l2_queryctrl *qc)
1220{
1221 int i;
1222
1223 for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
1224 if (qc->id && qc->id == tm6000_qctrl[i].id) {
1225 memcpy(qc, &(tm6000_qctrl[i]),
1226 sizeof(*qc));
1227 return 0;
1228 }
1229
1230 return -EINVAL;
1231}
1232 1143
1233static int vidioc_g_ctrl(struct file *file, void *priv, 1144static int tm6000_s_ctrl(struct v4l2_ctrl *ctrl)
1234 struct v4l2_control *ctrl)
1235{ 1145{
1236 struct tm6000_fh *fh = priv; 1146 struct tm6000_core *dev = container_of(ctrl->handler, struct tm6000_core, ctrl_handler);
1237 struct tm6000_core *dev = fh->dev; 1147 u8 val = ctrl->val;
1238 int val;
1239 1148
1240 /* FIXME: Probably, those won't work! Maybe we need shadow regs */
1241 switch (ctrl->id) { 1149 switch (ctrl->id) {
1242 case V4L2_CID_CONTRAST: 1150 case V4L2_CID_CONTRAST:
1243 val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0); 1151 tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
1244 break; 1152 return 0;
1245 case V4L2_CID_BRIGHTNESS: 1153 case V4L2_CID_BRIGHTNESS:
1246 val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0); 1154 tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
1247 return 0; 1155 return 0;
1248 case V4L2_CID_SATURATION: 1156 case V4L2_CID_SATURATION:
1249 val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0); 1157 tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
1250 return 0; 1158 return 0;
1251 case V4L2_CID_HUE: 1159 case V4L2_CID_HUE:
1252 val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0); 1160 tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
1253 return 0;
1254 case V4L2_CID_AUDIO_MUTE:
1255 val = dev->ctl_mute;
1256 return 0;
1257 case V4L2_CID_AUDIO_VOLUME:
1258 val = dev->ctl_volume;
1259 return 0; 1161 return 0;
1260 default:
1261 return -EINVAL;
1262 } 1162 }
1163 return -EINVAL;
1164}
1263 1165
1264 if (val < 0) 1166static const struct v4l2_ctrl_ops tm6000_ctrl_ops = {
1265 return val; 1167 .s_ctrl = tm6000_s_ctrl,
1266 1168};
1267 ctrl->value = val;
1268 1169
1269 return 0; 1170static int tm6000_radio_s_ctrl(struct v4l2_ctrl *ctrl)
1270}
1271static int vidioc_s_ctrl(struct file *file, void *priv,
1272 struct v4l2_control *ctrl)
1273{ 1171{
1274 struct tm6000_fh *fh = priv; 1172 struct tm6000_core *dev = container_of(ctrl->handler,
1275 struct tm6000_core *dev = fh->dev; 1173 struct tm6000_core, radio_ctrl_handler);
1276 u8 val = ctrl->value; 1174 u8 val = ctrl->val;
1277 1175
1278 switch (ctrl->id) { 1176 switch (ctrl->id) {
1279 case V4L2_CID_CONTRAST:
1280 tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
1281 return 0;
1282 case V4L2_CID_BRIGHTNESS:
1283 tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
1284 return 0;
1285 case V4L2_CID_SATURATION:
1286 tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
1287 return 0;
1288 case V4L2_CID_HUE:
1289 tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
1290 return 0;
1291 case V4L2_CID_AUDIO_MUTE: 1177 case V4L2_CID_AUDIO_MUTE:
1292 dev->ctl_mute = val; 1178 dev->ctl_mute = val;
1293 tm6000_tvaudio_set_mute(dev, val); 1179 tm6000_tvaudio_set_mute(dev, val);
@@ -1300,6 +1186,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
1300 return -EINVAL; 1186 return -EINVAL;
1301} 1187}
1302 1188
1189static const struct v4l2_ctrl_ops tm6000_radio_ctrl_ops = {
1190 .s_ctrl = tm6000_radio_s_ctrl,
1191};
1192
1303static int vidioc_g_tuner(struct file *file, void *priv, 1193static int vidioc_g_tuner(struct file *file, void *priv,
1304 struct v4l2_tuner *t) 1194 struct v4l2_tuner *t)
1305{ 1195{
@@ -1418,23 +1308,6 @@ static int radio_s_tuner(struct file *file, void *priv,
1418 return 0; 1308 return 0;
1419} 1309}
1420 1310
1421static int radio_queryctrl(struct file *file, void *priv,
1422 struct v4l2_queryctrl *c)
1423{
1424 const struct v4l2_queryctrl *ctrl;
1425
1426 if (c->id < V4L2_CID_BASE ||
1427 c->id >= V4L2_CID_LASTP1)
1428 return -EINVAL;
1429 if (c->id == V4L2_CID_AUDIO_MUTE) {
1430 ctrl = ctrl_by_id(c->id);
1431 *c = *ctrl;
1432 } else
1433 *c = no_ctrl;
1434
1435 return 0;
1436}
1437
1438/* ------------------------------------------------------------------ 1311/* ------------------------------------------------------------------
1439 File operations for the device 1312 File operations for the device
1440 ------------------------------------------------------------------*/ 1313 ------------------------------------------------------------------*/
@@ -1445,7 +1318,7 @@ static int __tm6000_open(struct file *file)
1445 struct tm6000_core *dev = video_drvdata(file); 1318 struct tm6000_core *dev = video_drvdata(file);
1446 struct tm6000_fh *fh; 1319 struct tm6000_fh *fh;
1447 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1320 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1448 int i, rc; 1321 int rc;
1449 int radio = 0; 1322 int radio = 0;
1450 1323
1451 dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n", 1324 dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
@@ -1505,13 +1378,7 @@ static int __tm6000_open(struct file *file)
1505 if (rc < 0) 1378 if (rc < 0)
1506 return rc; 1379 return rc;
1507 1380
1508 if (dev->mode != TM6000_MODE_ANALOG) { 1381 dev->mode = TM6000_MODE_ANALOG;
1509 /* Put all controls at a sane state */
1510 for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
1511 qctl_regs[i] = tm6000_qctrl[i].default_value;
1512
1513 dev->mode = TM6000_MODE_ANALOG;
1514 }
1515 1382
1516 if (!fh->radio) { 1383 if (!fh->radio) {
1517 videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops, 1384 videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
@@ -1678,9 +1545,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
1678 .vidioc_enum_input = vidioc_enum_input, 1545 .vidioc_enum_input = vidioc_enum_input,
1679 .vidioc_g_input = vidioc_g_input, 1546 .vidioc_g_input = vidioc_g_input,
1680 .vidioc_s_input = vidioc_s_input, 1547 .vidioc_s_input = vidioc_s_input,
1681 .vidioc_queryctrl = vidioc_queryctrl,
1682 .vidioc_g_ctrl = vidioc_g_ctrl,
1683 .vidioc_s_ctrl = vidioc_s_ctrl,
1684 .vidioc_g_tuner = vidioc_g_tuner, 1548 .vidioc_g_tuner = vidioc_g_tuner,
1685 .vidioc_s_tuner = vidioc_s_tuner, 1549 .vidioc_s_tuner = vidioc_s_tuner,
1686 .vidioc_g_frequency = vidioc_g_frequency, 1550 .vidioc_g_frequency = vidioc_g_frequency,
@@ -1713,9 +1577,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
1713 .vidioc_querycap = vidioc_querycap, 1577 .vidioc_querycap = vidioc_querycap,
1714 .vidioc_g_tuner = radio_g_tuner, 1578 .vidioc_g_tuner = radio_g_tuner,
1715 .vidioc_s_tuner = radio_s_tuner, 1579 .vidioc_s_tuner = radio_s_tuner,
1716 .vidioc_queryctrl = radio_queryctrl,
1717 .vidioc_g_ctrl = vidioc_g_ctrl,
1718 .vidioc_s_ctrl = vidioc_s_ctrl,
1719 .vidioc_g_frequency = vidioc_g_frequency, 1580 .vidioc_g_frequency = vidioc_g_frequency,
1720 .vidioc_s_frequency = vidioc_s_frequency, 1581 .vidioc_s_frequency = vidioc_s_frequency,
1721}; 1582};
@@ -1755,15 +1616,41 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
1755 1616
1756int tm6000_v4l2_register(struct tm6000_core *dev) 1617int tm6000_v4l2_register(struct tm6000_core *dev)
1757{ 1618{
1758 int ret = -1; 1619 int ret = 0;
1620
1621 v4l2_ctrl_handler_init(&dev->ctrl_handler, 6);
1622 v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 2);
1623 v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops,
1624 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
1625 v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops,
1626 V4L2_CID_AUDIO_VOLUME, -15, 15, 1, 0);
1627 v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
1628 V4L2_CID_BRIGHTNESS, 0, 255, 1, 54);
1629 v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
1630 V4L2_CID_CONTRAST, 0, 255, 1, 119);
1631 v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
1632 V4L2_CID_SATURATION, 0, 255, 1, 112);
1633 v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops,
1634 V4L2_CID_HUE, -128, 127, 1, 0);
1635 v4l2_ctrl_add_handler(&dev->ctrl_handler,
1636 &dev->radio_ctrl_handler, NULL);
1637
1638 if (dev->radio_ctrl_handler.error)
1639 ret = dev->radio_ctrl_handler.error;
1640 if (!ret && dev->ctrl_handler.error)
1641 ret = dev->ctrl_handler.error;
1642 if (ret)
1643 goto free_ctrl;
1759 1644
1760 dev->vfd = vdev_init(dev, &tm6000_template, "video"); 1645 dev->vfd = vdev_init(dev, &tm6000_template, "video");
1761 1646
1762 if (!dev->vfd) { 1647 if (!dev->vfd) {
1763 printk(KERN_INFO "%s: can't register video device\n", 1648 printk(KERN_INFO "%s: can't register video device\n",
1764 dev->name); 1649 dev->name);
1765 return -ENOMEM; 1650 ret = -ENOMEM;
1651 goto free_ctrl;
1766 } 1652 }
1653 dev->vfd->ctrl_handler = &dev->ctrl_handler;
1767 1654
1768 /* init video dma queues */ 1655 /* init video dma queues */
1769 INIT_LIST_HEAD(&dev->vidq.active); 1656 INIT_LIST_HEAD(&dev->vidq.active);
@@ -1774,7 +1661,9 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
1774 if (ret < 0) { 1661 if (ret < 0) {
1775 printk(KERN_INFO "%s: can't register video device\n", 1662 printk(KERN_INFO "%s: can't register video device\n",
1776 dev->name); 1663 dev->name);
1777 return ret; 1664 video_device_release(dev->vfd);
1665 dev->vfd = NULL;
1666 goto free_ctrl;
1778 } 1667 }
1779 1668
1780 printk(KERN_INFO "%s: registered device %s\n", 1669 printk(KERN_INFO "%s: registered device %s\n",
@@ -1787,15 +1676,17 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
1787 printk(KERN_INFO "%s: can't register radio device\n", 1676 printk(KERN_INFO "%s: can't register radio device\n",
1788 dev->name); 1677 dev->name);
1789 ret = -ENXIO; 1678 ret = -ENXIO;
1790 return ret; /* FIXME release resource */ 1679 goto unreg_video;
1791 } 1680 }
1792 1681
1682 dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
1793 ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, 1683 ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
1794 radio_nr); 1684 radio_nr);
1795 if (ret < 0) { 1685 if (ret < 0) {
1796 printk(KERN_INFO "%s: can't register radio device\n", 1686 printk(KERN_INFO "%s: can't register radio device\n",
1797 dev->name); 1687 dev->name);
1798 return ret; /* FIXME release resource */ 1688 video_device_release(dev->radio_dev);
1689 goto unreg_video;
1799 } 1690 }
1800 1691
1801 printk(KERN_INFO "%s: registered device %s\n", 1692 printk(KERN_INFO "%s: registered device %s\n",
@@ -1804,6 +1695,13 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
1804 1695
1805 printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); 1696 printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
1806 return ret; 1697 return ret;
1698
1699unreg_video:
1700 video_unregister_device(dev->vfd);
1701free_ctrl:
1702 v4l2_ctrl_handler_free(&dev->ctrl_handler);
1703 v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
1704 return ret;
1807} 1705}
1808 1706
1809int tm6000_v4l2_unregister(struct tm6000_core *dev) 1707int tm6000_v4l2_unregister(struct tm6000_core *dev)
diff --git a/drivers/media/usb/tm6000/tm6000.h b/drivers/media/usb/tm6000/tm6000.h
index 173dcd7a7284..a9ac262fcc93 100644
--- a/drivers/media/usb/tm6000/tm6000.h
+++ b/drivers/media/usb/tm6000/tm6000.h
@@ -27,6 +27,7 @@
27#include <linux/i2c.h> 27#include <linux/i2c.h>
28#include <linux/mutex.h> 28#include <linux/mutex.h>
29#include <media/v4l2-device.h> 29#include <media/v4l2-device.h>
30#include <media/v4l2-ctrls.h>
30 31
31#include <linux/dvb/frontend.h> 32#include <linux/dvb/frontend.h>
32#include "dvb_demux.h" 33#include "dvb_demux.h"
@@ -222,6 +223,8 @@ struct tm6000_core {
222 struct video_device *radio_dev; 223 struct video_device *radio_dev;
223 struct tm6000_dmaqueue vidq; 224 struct tm6000_dmaqueue vidq;
224 struct v4l2_device v4l2_dev; 225 struct v4l2_device v4l2_dev;
226 struct v4l2_ctrl_handler ctrl_handler;
227 struct v4l2_ctrl_handler radio_ctrl_handler;
225 228
226 int input; 229 int input;
227 struct tm6000_input vinput[3]; /* video input */ 230 struct tm6000_input vinput[3]; /* video input */