aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-11 08:07:45 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-06 17:09:17 -0400
commit8c7cb12ac1cc4ecc318765e0e2dcd853fa4a4d62 (patch)
tree58c579cbffffc169bff4652fcb90f3616ef795bb /drivers
parentbac639818c2c720ea8f79f932601f9209579bf14 (diff)
[media] cx88: each device node gets the right controls
radio only sees audio controls, video sees video and audio and vbi sees none. Also disable the chroma_agc control if secam is selected. 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/video/cx88/cx88-cards.c15
-rw-r--r--drivers/media/video/cx88/cx88-core.c7
-rw-r--r--drivers/media/video/cx88/cx88-video.c139
-rw-r--r--drivers/media/video/cx88/cx88.h4
4 files changed, 108 insertions, 57 deletions
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index cd8c3bf698ea..4e9d4f722960 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -3693,14 +3693,22 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
3693 return NULL; 3693 return NULL;
3694 } 3694 }
3695 3695
3696 if (v4l2_ctrl_handler_init(&core->hdl, 13)) { 3696 if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) {
3697 v4l2_device_unregister(&core->v4l2_dev);
3698 kfree(core);
3699 return NULL;
3700 }
3701
3702 if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) {
3703 v4l2_ctrl_handler_free(&core->video_hdl);
3697 v4l2_device_unregister(&core->v4l2_dev); 3704 v4l2_device_unregister(&core->v4l2_dev);
3698 kfree(core); 3705 kfree(core);
3699 return NULL; 3706 return NULL;
3700 } 3707 }
3701 3708
3702 if (0 != cx88_get_resources(core, pci)) { 3709 if (0 != cx88_get_resources(core, pci)) {
3703 v4l2_ctrl_handler_free(&core->hdl); 3710 v4l2_ctrl_handler_free(&core->video_hdl);
3711 v4l2_ctrl_handler_free(&core->audio_hdl);
3704 v4l2_device_unregister(&core->v4l2_dev); 3712 v4l2_device_unregister(&core->v4l2_dev);
3705 kfree(core); 3713 kfree(core);
3706 return NULL; 3714 return NULL;
@@ -3715,7 +3723,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
3715 if (core->lmmio == NULL) { 3723 if (core->lmmio == NULL) {
3716 release_mem_region(pci_resource_start(pci, 0), 3724 release_mem_region(pci_resource_start(pci, 0),
3717 pci_resource_len(pci, 0)); 3725 pci_resource_len(pci, 0));
3718 v4l2_ctrl_handler_free(&core->hdl); 3726 v4l2_ctrl_handler_free(&core->video_hdl);
3727 v4l2_ctrl_handler_free(&core->audio_hdl);
3719 v4l2_device_unregister(&core->v4l2_dev); 3728 v4l2_device_unregister(&core->v4l2_dev);
3720 kfree(core); 3729 kfree(core);
3721 return NULL; 3730 return NULL;
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index a6480aaa8a0b..8bd925db412b 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1012,6 +1012,9 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
1012 // tell i2c chips 1012 // tell i2c chips
1013 call_all(core, core, s_std, norm); 1013 call_all(core, core, s_std, norm);
1014 1014
1015 /* The chroma_agc control should be inaccessible if the video format is SECAM */
1016 v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
1017
1015 // done 1018 // done
1016 return 0; 1019 return 0;
1017} 1020}
@@ -1030,7 +1033,6 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
1030 return NULL; 1033 return NULL;
1031 *vfd = *template_; 1034 *vfd = *template_;
1032 vfd->v4l2_dev = &core->v4l2_dev; 1035 vfd->v4l2_dev = &core->v4l2_dev;
1033 vfd->ctrl_handler = &core->hdl;
1034 vfd->release = video_device_release; 1036 vfd->release = video_device_release;
1035 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", 1037 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1036 core->name, type, core->board.name); 1038 core->name, type, core->board.name);
@@ -1086,7 +1088,8 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1086 iounmap(core->lmmio); 1088 iounmap(core->lmmio);
1087 cx88_devcount--; 1089 cx88_devcount--;
1088 mutex_unlock(&devlist); 1090 mutex_unlock(&devlist);
1089 v4l2_ctrl_handler_free(&core->hdl); 1091 v4l2_ctrl_handler_free(&core->video_hdl);
1092 v4l2_ctrl_handler_free(&core->audio_hdl);
1090 v4l2_device_unregister(&core->v4l2_dev); 1093 v4l2_device_unregister(&core->v4l2_dev);
1091 kfree(core); 1094 kfree(core);
1092} 1095}
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 2f3d4df33f7e..104a85c265f3 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -155,12 +155,6 @@ static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
155 155
156/* ------------------------------------------------------------------- */ 156/* ------------------------------------------------------------------- */
157 157
158static const struct v4l2_queryctrl no_ctl = {
159 .name = "42",
160 .flags = V4L2_CTRL_FLAG_DISABLED,
161};
162
163
164struct cx88_ctrl { 158struct cx88_ctrl {
165 /* control information */ 159 /* control information */
166 u32 id; 160 u32 id;
@@ -177,7 +171,7 @@ struct cx88_ctrl {
177 u32 shift; 171 u32 shift;
178}; 172};
179 173
180static const struct cx88_ctrl cx8800_ctls[] = { 174static const struct cx88_ctrl cx8800_vid_ctls[] = {
181 /* --- video --- */ 175 /* --- video --- */
182 { 176 {
183 .id = V4L2_CID_BRIGHTNESS, 177 .id = V4L2_CID_BRIGHTNESS,
@@ -260,7 +254,11 @@ static const struct cx88_ctrl cx8800_ctls[] = {
260 .reg = MO_HTOTAL, 254 .reg = MO_HTOTAL,
261 .mask = 3 << 11, 255 .mask = 3 << 11,
262 .shift = 11, 256 .shift = 11,
263 }, { 257 }
258};
259
260static const struct cx88_ctrl cx8800_aud_ctls[] = {
261 {
264 /* --- audio --- */ 262 /* --- audio --- */
265 .id = V4L2_CID_AUDIO_MUTE, 263 .id = V4L2_CID_AUDIO_MUTE,
266 .minimum = 0, 264 .minimum = 0,
@@ -293,14 +291,10 @@ static const struct cx88_ctrl cx8800_ctls[] = {
293 } 291 }
294}; 292};
295 293
296enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) }; 294enum {
297 295 CX8800_VID_CTLS = ARRAY_SIZE(cx8800_vid_ctls),
298 296 CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
299int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl) 297};
300{
301 return 0;
302}
303EXPORT_SYMBOL(cx8800_ctrl_query);
304 298
305/* ------------------------------------------------------------------- */ 299/* ------------------------------------------------------------------- */
306/* resource management */ 300/* resource management */
@@ -908,10 +902,56 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
908/* ------------------------------------------------------------------ */ 902/* ------------------------------------------------------------------ */
909/* VIDEO CTRL IOCTLS */ 903/* VIDEO CTRL IOCTLS */
910 904
911static int cx8800_s_ctrl(struct v4l2_ctrl *ctrl) 905static int cx8800_s_vid_ctrl(struct v4l2_ctrl *ctrl)
906{
907 struct cx88_core *core =
908 container_of(ctrl->handler, struct cx88_core, video_hdl);
909 const struct cx88_ctrl *cc = ctrl->priv;
910 u32 value, mask;
911
912 mask = cc->mask;
913 switch (ctrl->id) {
914 case V4L2_CID_SATURATION:
915 /* special v_sat handling */
916
917 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
918
919 if (core->tvnorm & V4L2_STD_SECAM) {
920 /* For SECAM, both U and V sat should be equal */
921 value = value << 8 | value;
922 } else {
923 /* Keeps U Saturation proportional to V Sat */
924 value = (value * 0x5a) / 0x7f << 8 | value;
925 }
926 mask = 0xffff;
927 break;
928 case V4L2_CID_SHARPNESS:
929 /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
930 value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7));
931 /* needs to be set for both fields */
932 cx_andor(MO_FILTER_EVEN, mask, value);
933 break;
934 case V4L2_CID_CHROMA_AGC:
935 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
936 break;
937 default:
938 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
939 break;
940 }
941 dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
942 ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
943 mask, cc->sreg ? " [shadowed]" : "");
944 if (cc->sreg)
945 cx_sandor(cc->sreg, cc->reg, mask, value);
946 else
947 cx_andor(cc->reg, mask, value);
948 return 0;
949}
950
951static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl)
912{ 952{
913 struct cx88_core *core = 953 struct cx88_core *core =
914 container_of(ctrl->handler, struct cx88_core, hdl); 954 container_of(ctrl->handler, struct cx88_core, audio_hdl);
915 const struct cx88_ctrl *cc = ctrl->priv; 955 const struct cx88_ctrl *cc = ctrl->priv;
916 u32 value,mask; 956 u32 value,mask;
917 957
@@ -941,32 +981,6 @@ static int cx8800_s_ctrl(struct v4l2_ctrl *ctrl)
941 case V4L2_CID_AUDIO_VOLUME: 981 case V4L2_CID_AUDIO_VOLUME:
942 value = 0x3f - (ctrl->val & 0x3f); 982 value = 0x3f - (ctrl->val & 0x3f);
943 break; 983 break;
944 case V4L2_CID_SATURATION:
945 /* special v_sat handling */
946
947 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
948
949 if (core->tvnorm & V4L2_STD_SECAM) {
950 /* For SECAM, both U and V sat should be equal */
951 value=value<<8|value;
952 } else {
953 /* Keeps U Saturation proportional to V Sat */
954 value=(value*0x5a)/0x7f<<8|value;
955 }
956 mask=0xffff;
957 break;
958 case V4L2_CID_SHARPNESS:
959 /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
960 value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7));
961 /* needs to be set for both fields */
962 cx_andor(MO_FILTER_EVEN, mask, value);
963 break;
964 case V4L2_CID_CHROMA_AGC:
965 /* Do not allow chroma AGC to be enabled for SECAM */
966 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
967 if ((core->tvnorm & V4L2_STD_SECAM) && value)
968 return -EINVAL;
969 break;
970 default: 984 default:
971 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; 985 value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
972 break; 986 break;
@@ -1599,8 +1613,12 @@ static const struct video_device cx8800_radio_template = {
1599 .ioctl_ops = &radio_ioctl_ops, 1613 .ioctl_ops = &radio_ioctl_ops,
1600}; 1614};
1601 1615
1602static const struct v4l2_ctrl_ops cx8800_ctrl_ops = { 1616static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = {
1603 .s_ctrl = cx8800_s_ctrl, 1617 .s_ctrl = cx8800_s_vid_ctrl,
1618};
1619
1620static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = {
1621 .s_ctrl = cx8800_s_aud_ctrl,
1604}; 1622};
1605 1623
1606/* ----------------------------------------------------------- */ 1624/* ----------------------------------------------------------- */
@@ -1707,18 +1725,34 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1707 } 1725 }
1708 cx_set(MO_PCI_INTMSK, core->pci_irqmask); 1726 cx_set(MO_PCI_INTMSK, core->pci_irqmask);
1709 1727
1710 for (i = 0; i < CX8800_CTLS; i++) { 1728 for (i = 0; i < CX8800_AUD_CTLS; i++) {
1711 const struct cx88_ctrl *cc = &cx8800_ctls[i]; 1729 const struct cx88_ctrl *cc = &cx8800_aud_ctls[i];
1730 struct v4l2_ctrl *vc;
1731
1732 vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops,
1733 cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
1734 if (vc == NULL) {
1735 err = core->audio_hdl.error;
1736 goto fail_core;
1737 }
1738 vc->priv = (void *)cc;
1739 }
1740
1741 for (i = 0; i < CX8800_VID_CTLS; i++) {
1742 const struct cx88_ctrl *cc = &cx8800_vid_ctls[i];
1712 struct v4l2_ctrl *vc; 1743 struct v4l2_ctrl *vc;
1713 1744
1714 vc = v4l2_ctrl_new_std(&core->hdl, &cx8800_ctrl_ops, 1745 vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops,
1715 cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value); 1746 cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
1716 if (vc == NULL) { 1747 if (vc == NULL) {
1717 err = core->hdl.error; 1748 err = core->video_hdl.error;
1718 goto fail_core; 1749 goto fail_core;
1719 } 1750 }
1720 vc->priv = (void *)cc; 1751 vc->priv = (void *)cc;
1752 if (vc->id == V4L2_CID_CHROMA_AGC)
1753 core->chroma_agc = vc;
1721 } 1754 }
1755 v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl);
1722 1756
1723 /* load and configure helper modules */ 1757 /* load and configure helper modules */
1724 1758
@@ -1771,13 +1805,15 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1771 /* initial device configuration */ 1805 /* initial device configuration */
1772 mutex_lock(&core->lock); 1806 mutex_lock(&core->lock);
1773 cx88_set_tvnorm(core, core->tvnorm); 1807 cx88_set_tvnorm(core, core->tvnorm);
1774 v4l2_ctrl_handler_setup(&core->hdl); 1808 v4l2_ctrl_handler_setup(&core->video_hdl);
1809 v4l2_ctrl_handler_setup(&core->audio_hdl);
1775 cx88_video_mux(core, 0); 1810 cx88_video_mux(core, 0);
1776 1811
1777 /* register v4l devices */ 1812 /* register v4l devices */
1778 dev->video_dev = cx88_vdev_init(core,dev->pci, 1813 dev->video_dev = cx88_vdev_init(core,dev->pci,
1779 &cx8800_video_template,"video"); 1814 &cx8800_video_template,"video");
1780 video_set_drvdata(dev->video_dev, dev); 1815 video_set_drvdata(dev->video_dev, dev);
1816 dev->video_dev->ctrl_handler = &core->video_hdl;
1781 err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, 1817 err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
1782 video_nr[core->nr]); 1818 video_nr[core->nr]);
1783 if (err < 0) { 1819 if (err < 0) {
@@ -1804,6 +1840,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
1804 dev->radio_dev = cx88_vdev_init(core,dev->pci, 1840 dev->radio_dev = cx88_vdev_init(core,dev->pci,
1805 &cx8800_radio_template,"radio"); 1841 &cx8800_radio_template,"radio");
1806 video_set_drvdata(dev->radio_dev, dev); 1842 video_set_drvdata(dev->radio_dev, dev);
1843 dev->radio_dev->ctrl_handler = &core->audio_hdl;
1807 err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, 1844 err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
1808 radio_nr[core->nr]); 1845 radio_nr[core->nr]);
1809 if (err < 0) { 1846 if (err < 0) {
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index f12a77b4532d..280bf6ab7b75 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -350,7 +350,9 @@ struct cx88_core {
350 350
351 /* config info -- analog */ 351 /* config info -- analog */
352 struct v4l2_device v4l2_dev; 352 struct v4l2_device v4l2_dev;
353 struct v4l2_ctrl_handler hdl; 353 struct v4l2_ctrl_handler video_hdl;
354 struct v4l2_ctrl *chroma_agc;
355 struct v4l2_ctrl_handler audio_hdl;
354 struct v4l2_subdev *sd_wm8775; 356 struct v4l2_subdev *sd_wm8775;
355 struct i2c_client *i2c_rtc; 357 struct i2c_client *i2c_rtc;
356 unsigned int boardnr; 358 unsigned int boardnr;