Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
9f747359 2c2a0536

+70 -169
+67 -169
drivers/media/usb/tm6000/tm6000-video.c
··· 63 63 int tm6000_debug; 64 64 EXPORT_SYMBOL_GPL(tm6000_debug); 65 65 66 - static const struct v4l2_queryctrl no_ctrl = { 67 - .name = "42", 68 - .flags = V4L2_CTRL_FLAG_DISABLED, 69 - }; 70 - 71 - /* supported controls */ 72 - static 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 - 128 - static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl); 129 - static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)]; 130 - 131 66 static struct tm6000_fmt format[] = { 132 67 { 133 68 .name = "4:2:2, packed, YVY2", ··· 78 143 .depth = 16, 79 144 } 80 145 }; 81 - 82 - static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) 83 - { 84 - unsigned int i; 85 - 86 - for (i = 0; i < CTRLS; i++) 87 - if (tm6000_qctrl[i].id == id) 88 - return tm6000_qctrl+i; 89 - return NULL; 90 - } 91 146 92 147 /* ------------------------------------------------------------------ 93 148 * DMA and thread functions ··· 1140 1215 } 1141 1216 1142 1217 /* --- controls ---------------------------------------------- */ 1143 - static int vidioc_queryctrl(struct file *file, void *priv, 1144 - struct v4l2_queryctrl *qc) 1218 + 1219 + static int tm6000_s_ctrl(struct v4l2_ctrl *ctrl) 1145 1220 { 1146 - int i; 1147 - 1148 - for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) 1149 - if (qc->id && qc->id == tm6000_qctrl[i].id) { 1150 - memcpy(qc, &(tm6000_qctrl[i]), 1151 - sizeof(*qc)); 1152 - return 0; 1153 - } 1154 - 1155 - return -EINVAL; 1156 - } 1157 - 1158 - static int vidioc_g_ctrl(struct file *file, void *priv, 1159 - struct v4l2_control *ctrl) 1160 - { 1161 - struct tm6000_fh *fh = priv; 1162 - struct tm6000_core *dev = fh->dev; 1163 - int val; 1164 - 1165 - /* FIXME: Probably, those won't work! Maybe we need shadow regs */ 1166 - switch (ctrl->id) { 1167 - case V4L2_CID_CONTRAST: 1168 - val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0); 1169 - break; 1170 - case V4L2_CID_BRIGHTNESS: 1171 - val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0); 1172 - return 0; 1173 - case V4L2_CID_SATURATION: 1174 - val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0); 1175 - return 0; 1176 - case V4L2_CID_HUE: 1177 - val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0); 1178 - return 0; 1179 - case V4L2_CID_AUDIO_MUTE: 1180 - val = dev->ctl_mute; 1181 - return 0; 1182 - case V4L2_CID_AUDIO_VOLUME: 1183 - val = dev->ctl_volume; 1184 - return 0; 1185 - default: 1186 - return -EINVAL; 1187 - } 1188 - 1189 - if (val < 0) 1190 - return val; 1191 - 1192 - ctrl->value = val; 1193 - 1194 - return 0; 1195 - } 1196 - static int vidioc_s_ctrl(struct file *file, void *priv, 1197 - struct v4l2_control *ctrl) 1198 - { 1199 - struct tm6000_fh *fh = priv; 1200 - struct tm6000_core *dev = fh->dev; 1201 - u8 val = ctrl->value; 1221 + struct tm6000_core *dev = container_of(ctrl->handler, struct tm6000_core, ctrl_handler); 1222 + u8 val = ctrl->val; 1202 1223 1203 1224 switch (ctrl->id) { 1204 1225 case V4L2_CID_CONTRAST: ··· 1159 1288 case V4L2_CID_HUE: 1160 1289 tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val); 1161 1290 return 0; 1291 + } 1292 + return -EINVAL; 1293 + } 1294 + 1295 + static const struct v4l2_ctrl_ops tm6000_ctrl_ops = { 1296 + .s_ctrl = tm6000_s_ctrl, 1297 + }; 1298 + 1299 + static int tm6000_radio_s_ctrl(struct v4l2_ctrl *ctrl) 1300 + { 1301 + struct tm6000_core *dev = container_of(ctrl->handler, 1302 + struct tm6000_core, radio_ctrl_handler); 1303 + u8 val = ctrl->val; 1304 + 1305 + switch (ctrl->id) { 1162 1306 case V4L2_CID_AUDIO_MUTE: 1163 1307 dev->ctl_mute = val; 1164 1308 tm6000_tvaudio_set_mute(dev, val); ··· 1185 1299 } 1186 1300 return -EINVAL; 1187 1301 } 1302 + 1303 + static const struct v4l2_ctrl_ops tm6000_radio_ctrl_ops = { 1304 + .s_ctrl = tm6000_radio_s_ctrl, 1305 + }; 1188 1306 1189 1307 static int vidioc_g_tuner(struct file *file, void *priv, 1190 1308 struct v4l2_tuner *t) ··· 1308 1418 return 0; 1309 1419 } 1310 1420 1311 - static int radio_queryctrl(struct file *file, void *priv, 1312 - struct v4l2_queryctrl *c) 1313 - { 1314 - const struct v4l2_queryctrl *ctrl; 1315 - 1316 - if (c->id < V4L2_CID_BASE || 1317 - c->id >= V4L2_CID_LASTP1) 1318 - return -EINVAL; 1319 - if (c->id == V4L2_CID_AUDIO_MUTE) { 1320 - ctrl = ctrl_by_id(c->id); 1321 - *c = *ctrl; 1322 - } else 1323 - *c = no_ctrl; 1324 - 1325 - return 0; 1326 - } 1327 - 1328 1421 /* ------------------------------------------------------------------ 1329 1422 File operations for the device 1330 1423 ------------------------------------------------------------------*/ ··· 1318 1445 struct tm6000_core *dev = video_drvdata(file); 1319 1446 struct tm6000_fh *fh; 1320 1447 enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1321 - int i, rc; 1448 + int rc; 1322 1449 int radio = 0; 1323 1450 1324 1451 dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n", ··· 1378 1505 if (rc < 0) 1379 1506 return rc; 1380 1507 1381 - if (dev->mode != TM6000_MODE_ANALOG) { 1382 - /* Put all controls at a sane state */ 1383 - for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++) 1384 - qctl_regs[i] = tm6000_qctrl[i].default_value; 1385 - 1386 - dev->mode = TM6000_MODE_ANALOG; 1387 - } 1508 + dev->mode = TM6000_MODE_ANALOG; 1388 1509 1389 1510 if (!fh->radio) { 1390 1511 videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops, ··· 1545 1678 .vidioc_enum_input = vidioc_enum_input, 1546 1679 .vidioc_g_input = vidioc_g_input, 1547 1680 .vidioc_s_input = vidioc_s_input, 1548 - .vidioc_queryctrl = vidioc_queryctrl, 1549 - .vidioc_g_ctrl = vidioc_g_ctrl, 1550 - .vidioc_s_ctrl = vidioc_s_ctrl, 1551 1681 .vidioc_g_tuner = vidioc_g_tuner, 1552 1682 .vidioc_s_tuner = vidioc_s_tuner, 1553 1683 .vidioc_g_frequency = vidioc_g_frequency, ··· 1577 1713 .vidioc_querycap = vidioc_querycap, 1578 1714 .vidioc_g_tuner = radio_g_tuner, 1579 1715 .vidioc_s_tuner = radio_s_tuner, 1580 - .vidioc_queryctrl = radio_queryctrl, 1581 - .vidioc_g_ctrl = vidioc_g_ctrl, 1582 - .vidioc_s_ctrl = vidioc_s_ctrl, 1583 1716 .vidioc_g_frequency = vidioc_g_frequency, 1584 1717 .vidioc_s_frequency = vidioc_s_frequency, 1585 1718 }; ··· 1616 1755 1617 1756 int tm6000_v4l2_register(struct tm6000_core *dev) 1618 1757 { 1619 - int ret = -1; 1758 + int ret = 0; 1759 + 1760 + v4l2_ctrl_handler_init(&dev->ctrl_handler, 6); 1761 + v4l2_ctrl_handler_init(&dev->radio_ctrl_handler, 2); 1762 + v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops, 1763 + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); 1764 + v4l2_ctrl_new_std(&dev->radio_ctrl_handler, &tm6000_radio_ctrl_ops, 1765 + V4L2_CID_AUDIO_VOLUME, -15, 15, 1, 0); 1766 + v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops, 1767 + V4L2_CID_BRIGHTNESS, 0, 255, 1, 54); 1768 + v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops, 1769 + V4L2_CID_CONTRAST, 0, 255, 1, 119); 1770 + v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops, 1771 + V4L2_CID_SATURATION, 0, 255, 1, 112); 1772 + v4l2_ctrl_new_std(&dev->ctrl_handler, &tm6000_ctrl_ops, 1773 + V4L2_CID_HUE, -128, 127, 1, 0); 1774 + v4l2_ctrl_add_handler(&dev->ctrl_handler, 1775 + &dev->radio_ctrl_handler, NULL); 1776 + 1777 + if (dev->radio_ctrl_handler.error) 1778 + ret = dev->radio_ctrl_handler.error; 1779 + if (!ret && dev->ctrl_handler.error) 1780 + ret = dev->ctrl_handler.error; 1781 + if (ret) 1782 + goto free_ctrl; 1620 1783 1621 1784 dev->vfd = vdev_init(dev, &tm6000_template, "video"); 1622 1785 1623 1786 if (!dev->vfd) { 1624 1787 printk(KERN_INFO "%s: can't register video device\n", 1625 1788 dev->name); 1626 - return -ENOMEM; 1789 + ret = -ENOMEM; 1790 + goto free_ctrl; 1627 1791 } 1792 + dev->vfd->ctrl_handler = &dev->ctrl_handler; 1628 1793 1629 1794 /* init video dma queues */ 1630 1795 INIT_LIST_HEAD(&dev->vidq.active); ··· 1661 1774 if (ret < 0) { 1662 1775 printk(KERN_INFO "%s: can't register video device\n", 1663 1776 dev->name); 1664 - return ret; 1777 + video_device_release(dev->vfd); 1778 + dev->vfd = NULL; 1779 + goto free_ctrl; 1665 1780 } 1666 1781 1667 1782 printk(KERN_INFO "%s: registered device %s\n", ··· 1676 1787 printk(KERN_INFO "%s: can't register radio device\n", 1677 1788 dev->name); 1678 1789 ret = -ENXIO; 1679 - return ret; /* FIXME release resource */ 1790 + goto unreg_video; 1680 1791 } 1681 1792 1793 + dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler; 1682 1794 ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, 1683 1795 radio_nr); 1684 1796 if (ret < 0) { 1685 1797 printk(KERN_INFO "%s: can't register radio device\n", 1686 1798 dev->name); 1687 - return ret; /* FIXME release resource */ 1799 + video_device_release(dev->radio_dev); 1800 + goto unreg_video; 1688 1801 } 1689 1802 1690 1803 printk(KERN_INFO "%s: registered device %s\n", ··· 1694 1803 } 1695 1804 1696 1805 printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret); 1806 + return ret; 1807 + 1808 + unreg_video: 1809 + video_unregister_device(dev->vfd); 1810 + free_ctrl: 1811 + v4l2_ctrl_handler_free(&dev->ctrl_handler); 1812 + v4l2_ctrl_handler_free(&dev->radio_ctrl_handler); 1697 1813 return ret; 1698 1814 } 1699 1815
+3
drivers/media/usb/tm6000/tm6000.h
··· 27 27 #include <linux/i2c.h> 28 28 #include <linux/mutex.h> 29 29 #include <media/v4l2-device.h> 30 + #include <media/v4l2-ctrls.h> 30 31 31 32 #include <linux/dvb/frontend.h> 32 33 #include "dvb_demux.h" ··· 223 222 struct video_device *radio_dev; 224 223 struct tm6000_dmaqueue vidq; 225 224 struct v4l2_device v4l2_dev; 225 + struct v4l2_ctrl_handler ctrl_handler; 226 + struct v4l2_ctrl_handler radio_ctrl_handler; 226 227 227 228 int input; 228 229 struct tm6000_input vinput[3]; /* video input */