diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-06-10 06:39:52 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-06 17:08:23 -0400 |
commit | bac639818c2c720ea8f79f932601f9209579bf14 (patch) | |
tree | 05c6470f25f3dd1717c97949dbc9e6795f931b7d | |
parent | 902e197dcc36138e1f40f4435b7de8893ffc6c15 (diff) |
[media] cx88: first phase to convert cx88 to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/cx88/cx88-alsa.c | 31 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 71 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 3 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 493 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 48 |
6 files changed, 211 insertions, 446 deletions
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 04bf6627d362..dfac6e34859f 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -585,13 +585,10 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, | |||
585 | { | 585 | { |
586 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 586 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); |
587 | struct cx88_core *core = chip->core; | 587 | struct cx88_core *core = chip->core; |
588 | struct v4l2_control client_ctl; | ||
589 | int left = value->value.integer.value[0]; | 588 | int left = value->value.integer.value[0]; |
590 | int right = value->value.integer.value[1]; | 589 | int right = value->value.integer.value[1]; |
591 | int v, b; | 590 | int v, b; |
592 | 591 | ||
593 | memset(&client_ctl, 0, sizeof(client_ctl)); | ||
594 | |||
595 | /* Pass volume & balance onto any WM8775 */ | 592 | /* Pass volume & balance onto any WM8775 */ |
596 | if (left >= right) { | 593 | if (left >= right) { |
597 | v = left << 10; | 594 | v = left << 10; |
@@ -600,13 +597,8 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, | |||
600 | v = right << 10; | 597 | v = right << 10; |
601 | b = right ? 0xffff - (0x8000 * left) / right : 0x8000; | 598 | b = right ? 0xffff - (0x8000 * left) / right : 0x8000; |
602 | } | 599 | } |
603 | client_ctl.value = v; | 600 | wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v); |
604 | client_ctl.id = V4L2_CID_AUDIO_VOLUME; | 601 | wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b); |
605 | call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); | ||
606 | |||
607 | client_ctl.value = b; | ||
608 | client_ctl.id = V4L2_CID_AUDIO_BALANCE; | ||
609 | call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); | ||
610 | } | 602 | } |
611 | 603 | ||
612 | /* OK - TODO: test it */ | 604 | /* OK - TODO: test it */ |
@@ -687,14 +679,8 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, | |||
687 | cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); | 679 | cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); |
688 | /* Pass mute onto any WM8775 */ | 680 | /* Pass mute onto any WM8775 */ |
689 | if ((core->board.audio_chip == V4L2_IDENT_WM8775) && | 681 | if ((core->board.audio_chip == V4L2_IDENT_WM8775) && |
690 | ((1<<6) == bit)) { | 682 | ((1<<6) == bit)) |
691 | struct v4l2_control client_ctl; | 683 | wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit)); |
692 | |||
693 | memset(&client_ctl, 0, sizeof(client_ctl)); | ||
694 | client_ctl.value = 0 != (vol & bit); | ||
695 | client_ctl.id = V4L2_CID_AUDIO_MUTE; | ||
696 | call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); | ||
697 | } | ||
698 | ret = 1; | 684 | ret = 1; |
699 | } | 685 | } |
700 | spin_unlock_irq(&chip->reg_lock); | 686 | spin_unlock_irq(&chip->reg_lock); |
@@ -724,13 +710,10 @@ static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, | |||
724 | { | 710 | { |
725 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 711 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); |
726 | struct cx88_core *core = chip->core; | 712 | struct cx88_core *core = chip->core; |
727 | struct v4l2_control client_ctl; | 713 | s32 val; |
728 | |||
729 | memset(&client_ctl, 0, sizeof(client_ctl)); | ||
730 | client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; | ||
731 | call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl); | ||
732 | value->value.integer.value[0] = client_ctl.value ? 1 : 0; | ||
733 | 714 | ||
715 | val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS); | ||
716 | value->value.integer.value[0] = val ? 1 : 0; | ||
734 | return 0; | 717 | return 0; |
735 | } | 718 | } |
736 | 719 | ||
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index cbacdf634fd8..c9bbe9fc9c7e 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -685,43 +685,6 @@ static struct videobuf_queue_ops blackbird_qops = { | |||
685 | 685 | ||
686 | /* ------------------------------------------------------------------ */ | 686 | /* ------------------------------------------------------------------ */ |
687 | 687 | ||
688 | static const u32 *ctrl_classes[] = { | ||
689 | cx88_user_ctrls, | ||
690 | cx2341x_mpeg_ctrls, | ||
691 | NULL | ||
692 | }; | ||
693 | |||
694 | static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl) | ||
695 | { | ||
696 | qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); | ||
697 | if (qctrl->id == 0) | ||
698 | return -EINVAL; | ||
699 | |||
700 | /* Standard V4L2 controls */ | ||
701 | if (cx8800_ctrl_query(dev->core, qctrl) == 0) | ||
702 | return 0; | ||
703 | |||
704 | /* MPEG V4L2 controls */ | ||
705 | if (cx2341x_ctrl_query(&dev->params, qctrl)) | ||
706 | qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; | ||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | /* ------------------------------------------------------------------ */ | ||
711 | /* IOCTL Handlers */ | ||
712 | |||
713 | static int vidioc_querymenu (struct file *file, void *priv, | ||
714 | struct v4l2_querymenu *qmenu) | ||
715 | { | ||
716 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
717 | struct v4l2_queryctrl qctrl; | ||
718 | |||
719 | qctrl.id = qmenu->id; | ||
720 | blackbird_queryctrl(dev, &qctrl); | ||
721 | return v4l2_ctrl_query_menu(qmenu, &qctrl, | ||
722 | cx2341x_ctrl_get_menu(&dev->params, qmenu->id)); | ||
723 | } | ||
724 | |||
725 | static int vidioc_querycap(struct file *file, void *priv, | 688 | static int vidioc_querycap(struct file *file, void *priv, |
726 | struct v4l2_capability *cap) | 689 | struct v4l2_capability *cap) |
727 | { | 690 | { |
@@ -917,20 +880,6 @@ static int vidioc_log_status (struct file *file, void *priv) | |||
917 | return 0; | 880 | return 0; |
918 | } | 881 | } |
919 | 882 | ||
920 | static int vidioc_queryctrl (struct file *file, void *priv, | ||
921 | struct v4l2_queryctrl *qctrl) | ||
922 | { | ||
923 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
924 | |||
925 | if (blackbird_queryctrl(dev, qctrl) == 0) | ||
926 | return 0; | ||
927 | |||
928 | qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); | ||
929 | if (unlikely(qctrl->id == 0)) | ||
930 | return -EINVAL; | ||
931 | return cx8800_ctrl_query(dev->core, qctrl); | ||
932 | } | ||
933 | |||
934 | static int vidioc_enum_input (struct file *file, void *priv, | 883 | static int vidioc_enum_input (struct file *file, void *priv, |
935 | struct v4l2_input *i) | 884 | struct v4l2_input *i) |
936 | { | 885 | { |
@@ -938,22 +887,6 @@ static int vidioc_enum_input (struct file *file, void *priv, | |||
938 | return cx88_enum_input (core,i); | 887 | return cx88_enum_input (core,i); |
939 | } | 888 | } |
940 | 889 | ||
941 | static int vidioc_g_ctrl (struct file *file, void *priv, | ||
942 | struct v4l2_control *ctl) | ||
943 | { | ||
944 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
945 | return | ||
946 | cx88_get_control(core,ctl); | ||
947 | } | ||
948 | |||
949 | static int vidioc_s_ctrl (struct file *file, void *priv, | ||
950 | struct v4l2_control *ctl) | ||
951 | { | ||
952 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
953 | return | ||
954 | cx88_set_control(core,ctl); | ||
955 | } | ||
956 | |||
957 | static int vidioc_g_frequency (struct file *file, void *priv, | 890 | static int vidioc_g_frequency (struct file *file, void *priv, |
958 | struct v4l2_frequency *f) | 891 | struct v4l2_frequency *f) |
959 | { | 892 | { |
@@ -1178,7 +1111,6 @@ static const struct v4l2_file_operations mpeg_fops = | |||
1178 | }; | 1111 | }; |
1179 | 1112 | ||
1180 | static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | 1113 | static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { |
1181 | .vidioc_querymenu = vidioc_querymenu, | ||
1182 | .vidioc_querycap = vidioc_querycap, | 1114 | .vidioc_querycap = vidioc_querycap, |
1183 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 1115 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, |
1184 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1116 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
@@ -1195,10 +1127,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | |||
1195 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, | 1127 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, |
1196 | .vidioc_s_frequency = vidioc_s_frequency, | 1128 | .vidioc_s_frequency = vidioc_s_frequency, |
1197 | .vidioc_log_status = vidioc_log_status, | 1129 | .vidioc_log_status = vidioc_log_status, |
1198 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1199 | .vidioc_enum_input = vidioc_enum_input, | 1130 | .vidioc_enum_input = vidioc_enum_input, |
1200 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1201 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1202 | .vidioc_g_frequency = vidioc_g_frequency, | 1131 | .vidioc_g_frequency = vidioc_g_frequency, |
1203 | .vidioc_g_input = vidioc_g_input, | 1132 | .vidioc_g_input = vidioc_g_input, |
1204 | .vidioc_s_input = vidioc_s_input, | 1133 | .vidioc_s_input = vidioc_s_input, |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index cbd5d119a2c6..cd8c3bf698ea 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -3693,7 +3693,14 @@ 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)) { | ||
3697 | v4l2_device_unregister(&core->v4l2_dev); | ||
3698 | kfree(core); | ||
3699 | return NULL; | ||
3700 | } | ||
3701 | |||
3696 | if (0 != cx88_get_resources(core, pci)) { | 3702 | if (0 != cx88_get_resources(core, pci)) { |
3703 | v4l2_ctrl_handler_free(&core->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; |
@@ -3706,6 +3713,10 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) | |||
3706 | core->bmmio = (u8 __iomem *)core->lmmio; | 3713 | core->bmmio = (u8 __iomem *)core->lmmio; |
3707 | 3714 | ||
3708 | if (core->lmmio == NULL) { | 3715 | if (core->lmmio == NULL) { |
3716 | release_mem_region(pci_resource_start(pci, 0), | ||
3717 | pci_resource_len(pci, 0)); | ||
3718 | v4l2_ctrl_handler_free(&core->hdl); | ||
3719 | v4l2_device_unregister(&core->v4l2_dev); | ||
3709 | kfree(core); | 3720 | kfree(core); |
3710 | return NULL; | 3721 | return NULL; |
3711 | } | 3722 | } |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index fbfdd8067937..a6480aaa8a0b 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -1030,7 +1030,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, | |||
1030 | return NULL; | 1030 | return NULL; |
1031 | *vfd = *template_; | 1031 | *vfd = *template_; |
1032 | vfd->v4l2_dev = &core->v4l2_dev; | 1032 | vfd->v4l2_dev = &core->v4l2_dev; |
1033 | vfd->parent = &pci->dev; | 1033 | vfd->ctrl_handler = &core->hdl; |
1034 | vfd->release = video_device_release; | 1034 | vfd->release = video_device_release; |
1035 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", | 1035 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", |
1036 | core->name, type, core->board.name); | 1036 | core->name, type, core->board.name); |
@@ -1086,6 +1086,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) | |||
1086 | iounmap(core->lmmio); | 1086 | iounmap(core->lmmio); |
1087 | cx88_devcount--; | 1087 | cx88_devcount--; |
1088 | mutex_unlock(&devlist); | 1088 | mutex_unlock(&devlist); |
1089 | v4l2_ctrl_handler_free(&core->hdl); | ||
1089 | v4l2_device_unregister(&core->v4l2_dev); | 1090 | v4l2_device_unregister(&core->v4l2_dev); |
1090 | kfree(core); | 1091 | kfree(core); |
1091 | } | 1092 | } |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 5d9973680614..2f3d4df33f7e 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -160,210 +160,144 @@ static const struct v4l2_queryctrl no_ctl = { | |||
160 | .flags = V4L2_CTRL_FLAG_DISABLED, | 160 | .flags = V4L2_CTRL_FLAG_DISABLED, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | |||
164 | struct cx88_ctrl { | ||
165 | /* control information */ | ||
166 | u32 id; | ||
167 | s32 minimum; | ||
168 | s32 maximum; | ||
169 | u32 step; | ||
170 | s32 default_value; | ||
171 | |||
172 | /* control register information */ | ||
173 | u32 off; | ||
174 | u32 reg; | ||
175 | u32 sreg; | ||
176 | u32 mask; | ||
177 | u32 shift; | ||
178 | }; | ||
179 | |||
163 | static const struct cx88_ctrl cx8800_ctls[] = { | 180 | static const struct cx88_ctrl cx8800_ctls[] = { |
164 | /* --- video --- */ | 181 | /* --- video --- */ |
165 | { | 182 | { |
166 | .v = { | 183 | .id = V4L2_CID_BRIGHTNESS, |
167 | .id = V4L2_CID_BRIGHTNESS, | 184 | .minimum = 0x00, |
168 | .name = "Brightness", | 185 | .maximum = 0xff, |
169 | .minimum = 0x00, | 186 | .step = 1, |
170 | .maximum = 0xff, | 187 | .default_value = 0x7f, |
171 | .step = 1, | 188 | .off = 128, |
172 | .default_value = 0x7f, | 189 | .reg = MO_CONTR_BRIGHT, |
173 | .type = V4L2_CTRL_TYPE_INTEGER, | 190 | .mask = 0x00ff, |
174 | }, | 191 | .shift = 0, |
175 | .off = 128, | ||
176 | .reg = MO_CONTR_BRIGHT, | ||
177 | .mask = 0x00ff, | ||
178 | .shift = 0, | ||
179 | },{ | 192 | },{ |
180 | .v = { | 193 | .id = V4L2_CID_CONTRAST, |
181 | .id = V4L2_CID_CONTRAST, | 194 | .minimum = 0, |
182 | .name = "Contrast", | 195 | .maximum = 0xff, |
183 | .minimum = 0, | 196 | .step = 1, |
184 | .maximum = 0xff, | 197 | .default_value = 0x3f, |
185 | .step = 1, | 198 | .off = 0, |
186 | .default_value = 0x3f, | 199 | .reg = MO_CONTR_BRIGHT, |
187 | .type = V4L2_CTRL_TYPE_INTEGER, | 200 | .mask = 0xff00, |
188 | }, | 201 | .shift = 8, |
189 | .off = 0, | ||
190 | .reg = MO_CONTR_BRIGHT, | ||
191 | .mask = 0xff00, | ||
192 | .shift = 8, | ||
193 | },{ | 202 | },{ |
194 | .v = { | 203 | .id = V4L2_CID_HUE, |
195 | .id = V4L2_CID_HUE, | 204 | .minimum = 0, |
196 | .name = "Hue", | 205 | .maximum = 0xff, |
197 | .minimum = 0, | 206 | .step = 1, |
198 | .maximum = 0xff, | 207 | .default_value = 0x7f, |
199 | .step = 1, | 208 | .off = 128, |
200 | .default_value = 0x7f, | 209 | .reg = MO_HUE, |
201 | .type = V4L2_CTRL_TYPE_INTEGER, | 210 | .mask = 0x00ff, |
202 | }, | 211 | .shift = 0, |
203 | .off = 128, | ||
204 | .reg = MO_HUE, | ||
205 | .mask = 0x00ff, | ||
206 | .shift = 0, | ||
207 | },{ | 212 | },{ |
208 | /* strictly, this only describes only U saturation. | 213 | /* strictly, this only describes only U saturation. |
209 | * V saturation is handled specially through code. | 214 | * V saturation is handled specially through code. |
210 | */ | 215 | */ |
211 | .v = { | 216 | .id = V4L2_CID_SATURATION, |
212 | .id = V4L2_CID_SATURATION, | 217 | .minimum = 0, |
213 | .name = "Saturation", | 218 | .maximum = 0xff, |
214 | .minimum = 0, | 219 | .step = 1, |
215 | .maximum = 0xff, | 220 | .default_value = 0x7f, |
216 | .step = 1, | 221 | .off = 0, |
217 | .default_value = 0x7f, | 222 | .reg = MO_UV_SATURATION, |
218 | .type = V4L2_CTRL_TYPE_INTEGER, | 223 | .mask = 0x00ff, |
219 | }, | 224 | .shift = 0, |
220 | .off = 0, | ||
221 | .reg = MO_UV_SATURATION, | ||
222 | .mask = 0x00ff, | ||
223 | .shift = 0, | ||
224 | }, { | 225 | }, { |
225 | .v = { | 226 | .id = V4L2_CID_SHARPNESS, |
226 | .id = V4L2_CID_SHARPNESS, | 227 | .minimum = 0, |
227 | .name = "Sharpness", | 228 | .maximum = 4, |
228 | .minimum = 0, | 229 | .step = 1, |
229 | .maximum = 4, | 230 | .default_value = 0x0, |
230 | .step = 1, | 231 | .off = 0, |
231 | .default_value = 0x0, | ||
232 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
233 | }, | ||
234 | .off = 0, | ||
235 | /* NOTE: the value is converted and written to both even | 232 | /* NOTE: the value is converted and written to both even |
236 | and odd registers in the code */ | 233 | and odd registers in the code */ |
237 | .reg = MO_FILTER_ODD, | 234 | .reg = MO_FILTER_ODD, |
238 | .mask = 7 << 7, | 235 | .mask = 7 << 7, |
239 | .shift = 7, | 236 | .shift = 7, |
240 | }, { | 237 | }, { |
241 | .v = { | 238 | .id = V4L2_CID_CHROMA_AGC, |
242 | .id = V4L2_CID_CHROMA_AGC, | 239 | .minimum = 0, |
243 | .name = "Chroma AGC", | 240 | .maximum = 1, |
244 | .minimum = 0, | 241 | .default_value = 0x1, |
245 | .maximum = 1, | 242 | .reg = MO_INPUT_FORMAT, |
246 | .default_value = 0x1, | 243 | .mask = 1 << 10, |
247 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 244 | .shift = 10, |
248 | }, | ||
249 | .reg = MO_INPUT_FORMAT, | ||
250 | .mask = 1 << 10, | ||
251 | .shift = 10, | ||
252 | }, { | 245 | }, { |
253 | .v = { | 246 | .id = V4L2_CID_COLOR_KILLER, |
254 | .id = V4L2_CID_COLOR_KILLER, | 247 | .minimum = 0, |
255 | .name = "Color killer", | 248 | .maximum = 1, |
256 | .minimum = 0, | 249 | .default_value = 0x1, |
257 | .maximum = 1, | 250 | .reg = MO_INPUT_FORMAT, |
258 | .default_value = 0x1, | 251 | .mask = 1 << 9, |
259 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 252 | .shift = 9, |
260 | }, | ||
261 | .reg = MO_INPUT_FORMAT, | ||
262 | .mask = 1 << 9, | ||
263 | .shift = 9, | ||
264 | }, { | 253 | }, { |
265 | .v = { | 254 | .id = V4L2_CID_BAND_STOP_FILTER, |
266 | .id = V4L2_CID_BAND_STOP_FILTER, | 255 | .minimum = 0, |
267 | .name = "Notch filter", | 256 | .maximum = 1, |
268 | .minimum = 0, | 257 | .step = 1, |
269 | .maximum = 1, | 258 | .default_value = 0x0, |
270 | .step = 1, | 259 | .off = 0, |
271 | .default_value = 0x0, | 260 | .reg = MO_HTOTAL, |
272 | .type = V4L2_CTRL_TYPE_INTEGER, | 261 | .mask = 3 << 11, |
273 | }, | 262 | .shift = 11, |
274 | .off = 0, | ||
275 | .reg = MO_HTOTAL, | ||
276 | .mask = 3 << 11, | ||
277 | .shift = 11, | ||
278 | }, { | 263 | }, { |
279 | /* --- audio --- */ | 264 | /* --- audio --- */ |
280 | .v = { | 265 | .id = V4L2_CID_AUDIO_MUTE, |
281 | .id = V4L2_CID_AUDIO_MUTE, | 266 | .minimum = 0, |
282 | .name = "Mute", | 267 | .maximum = 1, |
283 | .minimum = 0, | 268 | .default_value = 1, |
284 | .maximum = 1, | 269 | .reg = AUD_VOL_CTL, |
285 | .default_value = 1, | 270 | .sreg = SHADOW_AUD_VOL_CTL, |
286 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 271 | .mask = (1 << 6), |
287 | }, | 272 | .shift = 6, |
288 | .reg = AUD_VOL_CTL, | ||
289 | .sreg = SHADOW_AUD_VOL_CTL, | ||
290 | .mask = (1 << 6), | ||
291 | .shift = 6, | ||
292 | },{ | 273 | },{ |
293 | .v = { | 274 | .id = V4L2_CID_AUDIO_VOLUME, |
294 | .id = V4L2_CID_AUDIO_VOLUME, | 275 | .minimum = 0, |
295 | .name = "Volume", | 276 | .maximum = 0x3f, |
296 | .minimum = 0, | 277 | .step = 1, |
297 | .maximum = 0x3f, | 278 | .default_value = 0x3f, |
298 | .step = 1, | 279 | .reg = AUD_VOL_CTL, |
299 | .default_value = 0x3f, | 280 | .sreg = SHADOW_AUD_VOL_CTL, |
300 | .type = V4L2_CTRL_TYPE_INTEGER, | 281 | .mask = 0x3f, |
301 | }, | 282 | .shift = 0, |
302 | .reg = AUD_VOL_CTL, | ||
303 | .sreg = SHADOW_AUD_VOL_CTL, | ||
304 | .mask = 0x3f, | ||
305 | .shift = 0, | ||
306 | },{ | 283 | },{ |
307 | .v = { | 284 | .id = V4L2_CID_AUDIO_BALANCE, |
308 | .id = V4L2_CID_AUDIO_BALANCE, | 285 | .minimum = 0, |
309 | .name = "Balance", | 286 | .maximum = 0x7f, |
310 | .minimum = 0, | 287 | .step = 1, |
311 | .maximum = 0x7f, | 288 | .default_value = 0x40, |
312 | .step = 1, | 289 | .reg = AUD_BAL_CTL, |
313 | .default_value = 0x40, | 290 | .sreg = SHADOW_AUD_BAL_CTL, |
314 | .type = V4L2_CTRL_TYPE_INTEGER, | 291 | .mask = 0x7f, |
315 | }, | 292 | .shift = 0, |
316 | .reg = AUD_BAL_CTL, | ||
317 | .sreg = SHADOW_AUD_BAL_CTL, | ||
318 | .mask = 0x7f, | ||
319 | .shift = 0, | ||
320 | } | 293 | } |
321 | }; | 294 | }; |
322 | enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) }; | ||
323 | 295 | ||
324 | /* Must be sorted from low to high control ID! */ | 296 | enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) }; |
325 | const u32 cx88_user_ctrls[] = { | ||
326 | V4L2_CID_USER_CLASS, | ||
327 | V4L2_CID_BRIGHTNESS, | ||
328 | V4L2_CID_CONTRAST, | ||
329 | V4L2_CID_SATURATION, | ||
330 | V4L2_CID_HUE, | ||
331 | V4L2_CID_AUDIO_VOLUME, | ||
332 | V4L2_CID_AUDIO_BALANCE, | ||
333 | V4L2_CID_AUDIO_MUTE, | ||
334 | V4L2_CID_SHARPNESS, | ||
335 | V4L2_CID_CHROMA_AGC, | ||
336 | V4L2_CID_COLOR_KILLER, | ||
337 | V4L2_CID_BAND_STOP_FILTER, | ||
338 | 0 | ||
339 | }; | ||
340 | EXPORT_SYMBOL(cx88_user_ctrls); | ||
341 | 297 | ||
342 | static const u32 * const ctrl_classes[] = { | ||
343 | cx88_user_ctrls, | ||
344 | NULL | ||
345 | }; | ||
346 | 298 | ||
347 | int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl) | 299 | int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl) |
348 | { | 300 | { |
349 | int i; | ||
350 | |||
351 | if (qctrl->id < V4L2_CID_BASE || | ||
352 | qctrl->id >= V4L2_CID_LASTP1) | ||
353 | return -EINVAL; | ||
354 | for (i = 0; i < CX8800_CTLS; i++) | ||
355 | if (cx8800_ctls[i].v.id == qctrl->id) | ||
356 | break; | ||
357 | if (i == CX8800_CTLS) { | ||
358 | *qctrl = no_ctl; | ||
359 | return 0; | ||
360 | } | ||
361 | *qctrl = cx8800_ctls[i].v; | ||
362 | /* Report chroma AGC as inactive when SECAM is selected */ | ||
363 | if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC && | ||
364 | core->tvnorm & V4L2_STD_SECAM) | ||
365 | qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | ||
366 | |||
367 | return 0; | 301 | return 0; |
368 | } | 302 | } |
369 | EXPORT_SYMBOL(cx8800_ctrl_query); | 303 | EXPORT_SYMBOL(cx8800_ctrl_query); |
@@ -974,98 +908,43 @@ video_mmap(struct file *file, struct vm_area_struct * vma) | |||
974 | /* ------------------------------------------------------------------ */ | 908 | /* ------------------------------------------------------------------ */ |
975 | /* VIDEO CTRL IOCTLS */ | 909 | /* VIDEO CTRL IOCTLS */ |
976 | 910 | ||
977 | int cx88_get_control (struct cx88_core *core, struct v4l2_control *ctl) | 911 | static int cx8800_s_ctrl(struct v4l2_ctrl *ctrl) |
978 | { | ||
979 | const struct cx88_ctrl *c = NULL; | ||
980 | u32 value; | ||
981 | int i; | ||
982 | |||
983 | for (i = 0; i < CX8800_CTLS; i++) | ||
984 | if (cx8800_ctls[i].v.id == ctl->id) | ||
985 | c = &cx8800_ctls[i]; | ||
986 | if (unlikely(NULL == c)) | ||
987 | return -EINVAL; | ||
988 | |||
989 | value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg); | ||
990 | switch (ctl->id) { | ||
991 | case V4L2_CID_AUDIO_BALANCE: | ||
992 | ctl->value = ((value & 0x7f) < 0x40) ? ((value & 0x7f) + 0x40) | ||
993 | : (0x7f - (value & 0x7f)); | ||
994 | break; | ||
995 | case V4L2_CID_AUDIO_VOLUME: | ||
996 | ctl->value = 0x3f - (value & 0x3f); | ||
997 | break; | ||
998 | case V4L2_CID_SHARPNESS: | ||
999 | ctl->value = ((value & 0x0200) ? (((value & 0x0180) >> 7) + 1) | ||
1000 | : 0); | ||
1001 | break; | ||
1002 | default: | ||
1003 | ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift; | ||
1004 | break; | ||
1005 | } | ||
1006 | dprintk(1,"get_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", | ||
1007 | ctl->id, c->v.name, ctl->value, c->reg, | ||
1008 | value,c->mask, c->sreg ? " [shadowed]" : ""); | ||
1009 | return 0; | ||
1010 | } | ||
1011 | EXPORT_SYMBOL(cx88_get_control); | ||
1012 | |||
1013 | int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) | ||
1014 | { | 912 | { |
1015 | const struct cx88_ctrl *c = NULL; | 913 | struct cx88_core *core = |
914 | container_of(ctrl->handler, struct cx88_core, hdl); | ||
915 | const struct cx88_ctrl *cc = ctrl->priv; | ||
1016 | u32 value,mask; | 916 | u32 value,mask; |
1017 | int i; | ||
1018 | |||
1019 | for (i = 0; i < CX8800_CTLS; i++) { | ||
1020 | if (cx8800_ctls[i].v.id == ctl->id) { | ||
1021 | c = &cx8800_ctls[i]; | ||
1022 | } | ||
1023 | } | ||
1024 | if (unlikely(NULL == c)) | ||
1025 | return -EINVAL; | ||
1026 | |||
1027 | if (ctl->value < c->v.minimum) | ||
1028 | ctl->value = c->v.minimum; | ||
1029 | if (ctl->value > c->v.maximum) | ||
1030 | ctl->value = c->v.maximum; | ||
1031 | 917 | ||
1032 | /* Pass changes onto any WM8775 */ | 918 | /* Pass changes onto any WM8775 */ |
1033 | if (core->board.audio_chip == V4L2_IDENT_WM8775) { | 919 | if (core->board.audio_chip == V4L2_IDENT_WM8775) { |
1034 | struct v4l2_control client_ctl; | 920 | switch (ctrl->id) { |
1035 | memset(&client_ctl, 0, sizeof(client_ctl)); | ||
1036 | client_ctl.id = ctl->id; | ||
1037 | |||
1038 | switch (ctl->id) { | ||
1039 | case V4L2_CID_AUDIO_MUTE: | 921 | case V4L2_CID_AUDIO_MUTE: |
1040 | client_ctl.value = ctl->value; | 922 | wm8775_s_ctrl(core, ctrl->id, ctrl->val); |
1041 | break; | 923 | break; |
1042 | case V4L2_CID_AUDIO_VOLUME: | 924 | case V4L2_CID_AUDIO_VOLUME: |
1043 | client_ctl.value = (ctl->value) ? | 925 | wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ? |
1044 | (0x90 + ctl->value) << 8 : 0; | 926 | (0x90 + ctrl->val) << 8 : 0); |
1045 | break; | 927 | break; |
1046 | case V4L2_CID_AUDIO_BALANCE: | 928 | case V4L2_CID_AUDIO_BALANCE: |
1047 | client_ctl.value = ctl->value << 9; | 929 | wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9); |
1048 | break; | 930 | break; |
1049 | default: | 931 | default: |
1050 | client_ctl.id = 0; | ||
1051 | break; | 932 | break; |
1052 | } | 933 | } |
1053 | if (client_ctl.id) | ||
1054 | call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); | ||
1055 | } | 934 | } |
1056 | 935 | ||
1057 | mask=c->mask; | 936 | mask = cc->mask; |
1058 | switch (ctl->id) { | 937 | switch (ctrl->id) { |
1059 | case V4L2_CID_AUDIO_BALANCE: | 938 | case V4L2_CID_AUDIO_BALANCE: |
1060 | value = (ctl->value < 0x40) ? (0x7f - ctl->value) : (ctl->value - 0x40); | 939 | value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40); |
1061 | break; | 940 | break; |
1062 | case V4L2_CID_AUDIO_VOLUME: | 941 | case V4L2_CID_AUDIO_VOLUME: |
1063 | value = 0x3f - (ctl->value & 0x3f); | 942 | value = 0x3f - (ctrl->val & 0x3f); |
1064 | break; | 943 | break; |
1065 | case V4L2_CID_SATURATION: | 944 | case V4L2_CID_SATURATION: |
1066 | /* special v_sat handling */ | 945 | /* special v_sat handling */ |
1067 | 946 | ||
1068 | value = ((ctl->value - c->off) << c->shift) & c->mask; | 947 | value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; |
1069 | 948 | ||
1070 | if (core->tvnorm & V4L2_STD_SECAM) { | 949 | if (core->tvnorm & V4L2_STD_SECAM) { |
1071 | /* For SECAM, both U and V sat should be equal */ | 950 | /* For SECAM, both U and V sat should be equal */ |
@@ -1078,44 +957,29 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl) | |||
1078 | break; | 957 | break; |
1079 | case V4L2_CID_SHARPNESS: | 958 | case V4L2_CID_SHARPNESS: |
1080 | /* 0b000, 0b100, 0b101, 0b110, or 0b111 */ | 959 | /* 0b000, 0b100, 0b101, 0b110, or 0b111 */ |
1081 | value = (ctl->value < 1 ? 0 : ((ctl->value + 3) << 7)); | 960 | value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7)); |
1082 | /* needs to be set for both fields */ | 961 | /* needs to be set for both fields */ |
1083 | cx_andor(MO_FILTER_EVEN, mask, value); | 962 | cx_andor(MO_FILTER_EVEN, mask, value); |
1084 | break; | 963 | break; |
1085 | case V4L2_CID_CHROMA_AGC: | 964 | case V4L2_CID_CHROMA_AGC: |
1086 | /* Do not allow chroma AGC to be enabled for SECAM */ | 965 | /* Do not allow chroma AGC to be enabled for SECAM */ |
1087 | value = ((ctl->value - c->off) << c->shift) & c->mask; | 966 | value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; |
1088 | if (core->tvnorm & V4L2_STD_SECAM && value) | 967 | if ((core->tvnorm & V4L2_STD_SECAM) && value) |
1089 | return -EINVAL; | 968 | return -EINVAL; |
1090 | break; | 969 | break; |
1091 | default: | 970 | default: |
1092 | value = ((ctl->value - c->off) << c->shift) & c->mask; | 971 | value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; |
1093 | break; | 972 | break; |
1094 | } | 973 | } |
1095 | dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", | 974 | dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", |
1096 | ctl->id, c->v.name, ctl->value, c->reg, value, | 975 | ctrl->id, ctrl->name, ctrl->val, cc->reg, value, |
1097 | mask, c->sreg ? " [shadowed]" : ""); | 976 | mask, cc->sreg ? " [shadowed]" : ""); |
1098 | if (c->sreg) { | 977 | if (cc->sreg) |
1099 | cx_sandor(c->sreg, c->reg, mask, value); | 978 | cx_sandor(cc->sreg, cc->reg, mask, value); |
1100 | } else { | 979 | else |
1101 | cx_andor(c->reg, mask, value); | 980 | cx_andor(cc->reg, mask, value); |
1102 | } | ||
1103 | return 0; | 981 | return 0; |
1104 | } | 982 | } |
1105 | EXPORT_SYMBOL(cx88_set_control); | ||
1106 | |||
1107 | static void init_controls(struct cx88_core *core) | ||
1108 | { | ||
1109 | struct v4l2_control ctrl; | ||
1110 | int i; | ||
1111 | |||
1112 | for (i = 0; i < CX8800_CTLS; i++) { | ||
1113 | ctrl.id=cx8800_ctls[i].v.id; | ||
1114 | ctrl.value=cx8800_ctls[i].v.default_value; | ||
1115 | |||
1116 | cx88_set_control(core, &ctrl); | ||
1117 | } | ||
1118 | } | ||
1119 | 983 | ||
1120 | /* ------------------------------------------------------------------ */ | 984 | /* ------------------------------------------------------------------ */ |
1121 | /* VIDEO IOCTLS */ | 985 | /* VIDEO IOCTLS */ |
@@ -1382,35 +1246,6 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i) | |||
1382 | return 0; | 1246 | return 0; |
1383 | } | 1247 | } |
1384 | 1248 | ||
1385 | |||
1386 | |||
1387 | static int vidioc_queryctrl (struct file *file, void *priv, | ||
1388 | struct v4l2_queryctrl *qctrl) | ||
1389 | { | ||
1390 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | ||
1391 | |||
1392 | qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); | ||
1393 | if (unlikely(qctrl->id == 0)) | ||
1394 | return -EINVAL; | ||
1395 | return cx8800_ctrl_query(core, qctrl); | ||
1396 | } | ||
1397 | |||
1398 | static int vidioc_g_ctrl (struct file *file, void *priv, | ||
1399 | struct v4l2_control *ctl) | ||
1400 | { | ||
1401 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | ||
1402 | return | ||
1403 | cx88_get_control(core,ctl); | ||
1404 | } | ||
1405 | |||
1406 | static int vidioc_s_ctrl (struct file *file, void *priv, | ||
1407 | struct v4l2_control *ctl) | ||
1408 | { | ||
1409 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | ||
1410 | return | ||
1411 | cx88_set_control(core,ctl); | ||
1412 | } | ||
1413 | |||
1414 | static int vidioc_g_tuner (struct file *file, void *priv, | 1249 | static int vidioc_g_tuner (struct file *file, void *priv, |
1415 | struct v4l2_tuner *t) | 1250 | struct v4l2_tuner *t) |
1416 | { | 1251 | { |
@@ -1563,29 +1398,6 @@ static int radio_s_tuner (struct file *file, void *priv, | |||
1563 | return 0; | 1398 | return 0; |
1564 | } | 1399 | } |
1565 | 1400 | ||
1566 | static int radio_queryctrl (struct file *file, void *priv, | ||
1567 | struct v4l2_queryctrl *c) | ||
1568 | { | ||
1569 | int i; | ||
1570 | |||
1571 | if (c->id < V4L2_CID_BASE || | ||
1572 | c->id >= V4L2_CID_LASTP1) | ||
1573 | return -EINVAL; | ||
1574 | if (c->id == V4L2_CID_AUDIO_MUTE || | ||
1575 | c->id == V4L2_CID_AUDIO_VOLUME || | ||
1576 | c->id == V4L2_CID_AUDIO_BALANCE) { | ||
1577 | for (i = 0; i < CX8800_CTLS; i++) { | ||
1578 | if (cx8800_ctls[i].v.id == c->id) | ||
1579 | break; | ||
1580 | } | ||
1581 | if (i == CX8800_CTLS) | ||
1582 | return -EINVAL; | ||
1583 | *c = cx8800_ctls[i].v; | ||
1584 | } else | ||
1585 | *c = no_ctl; | ||
1586 | return 0; | ||
1587 | } | ||
1588 | |||
1589 | /* ----------------------------------------------------------- */ | 1401 | /* ----------------------------------------------------------- */ |
1590 | 1402 | ||
1591 | static void cx8800_vid_timeout(unsigned long data) | 1403 | static void cx8800_vid_timeout(unsigned long data) |
@@ -1739,9 +1551,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1739 | .vidioc_enum_input = vidioc_enum_input, | 1551 | .vidioc_enum_input = vidioc_enum_input, |
1740 | .vidioc_g_input = vidioc_g_input, | 1552 | .vidioc_g_input = vidioc_g_input, |
1741 | .vidioc_s_input = vidioc_s_input, | 1553 | .vidioc_s_input = vidioc_s_input, |
1742 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1743 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1744 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1745 | .vidioc_streamon = vidioc_streamon, | 1554 | .vidioc_streamon = vidioc_streamon, |
1746 | .vidioc_streamoff = vidioc_streamoff, | 1555 | .vidioc_streamoff = vidioc_streamoff, |
1747 | .vidioc_g_tuner = vidioc_g_tuner, | 1556 | .vidioc_g_tuner = vidioc_g_tuner, |
@@ -1776,9 +1585,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { | |||
1776 | .vidioc_querycap = vidioc_querycap, | 1585 | .vidioc_querycap = vidioc_querycap, |
1777 | .vidioc_g_tuner = radio_g_tuner, | 1586 | .vidioc_g_tuner = radio_g_tuner, |
1778 | .vidioc_s_tuner = radio_s_tuner, | 1587 | .vidioc_s_tuner = radio_s_tuner, |
1779 | .vidioc_queryctrl = radio_queryctrl, | ||
1780 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1781 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1782 | .vidioc_g_frequency = vidioc_g_frequency, | 1588 | .vidioc_g_frequency = vidioc_g_frequency, |
1783 | .vidioc_s_frequency = vidioc_s_frequency, | 1589 | .vidioc_s_frequency = vidioc_s_frequency, |
1784 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1590 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -1793,6 +1599,10 @@ static const struct video_device cx8800_radio_template = { | |||
1793 | .ioctl_ops = &radio_ioctl_ops, | 1599 | .ioctl_ops = &radio_ioctl_ops, |
1794 | }; | 1600 | }; |
1795 | 1601 | ||
1602 | static const struct v4l2_ctrl_ops cx8800_ctrl_ops = { | ||
1603 | .s_ctrl = cx8800_s_ctrl, | ||
1604 | }; | ||
1605 | |||
1796 | /* ----------------------------------------------------------- */ | 1606 | /* ----------------------------------------------------------- */ |
1797 | 1607 | ||
1798 | static void cx8800_unregister_video(struct cx8800_dev *dev) | 1608 | static void cx8800_unregister_video(struct cx8800_dev *dev) |
@@ -1825,8 +1635,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1825 | { | 1635 | { |
1826 | struct cx8800_dev *dev; | 1636 | struct cx8800_dev *dev; |
1827 | struct cx88_core *core; | 1637 | struct cx88_core *core; |
1828 | |||
1829 | int err; | 1638 | int err; |
1639 | int i; | ||
1830 | 1640 | ||
1831 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | 1641 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); |
1832 | if (NULL == dev) | 1642 | if (NULL == dev) |
@@ -1897,6 +1707,19 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1897 | } | 1707 | } |
1898 | cx_set(MO_PCI_INTMSK, core->pci_irqmask); | 1708 | cx_set(MO_PCI_INTMSK, core->pci_irqmask); |
1899 | 1709 | ||
1710 | for (i = 0; i < CX8800_CTLS; i++) { | ||
1711 | const struct cx88_ctrl *cc = &cx8800_ctls[i]; | ||
1712 | struct v4l2_ctrl *vc; | ||
1713 | |||
1714 | vc = v4l2_ctrl_new_std(&core->hdl, &cx8800_ctrl_ops, | ||
1715 | cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value); | ||
1716 | if (vc == NULL) { | ||
1717 | err = core->hdl.error; | ||
1718 | goto fail_core; | ||
1719 | } | ||
1720 | vc->priv = (void *)cc; | ||
1721 | } | ||
1722 | |||
1900 | /* load and configure helper modules */ | 1723 | /* load and configure helper modules */ |
1901 | 1724 | ||
1902 | if (core->board.audio_chip == V4L2_IDENT_WM8775) { | 1725 | if (core->board.audio_chip == V4L2_IDENT_WM8775) { |
@@ -1914,8 +1737,10 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1914 | 1737 | ||
1915 | sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap, | 1738 | sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap, |
1916 | &wm8775_info, NULL); | 1739 | &wm8775_info, NULL); |
1917 | if (sd != NULL) | 1740 | if (sd != NULL) { |
1741 | core->sd_wm8775 = sd; | ||
1918 | sd->grp_id = WM8775_GID; | 1742 | sd->grp_id = WM8775_GID; |
1743 | } | ||
1919 | } | 1744 | } |
1920 | 1745 | ||
1921 | if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { | 1746 | if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { |
@@ -1946,7 +1771,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1946 | /* initial device configuration */ | 1771 | /* initial device configuration */ |
1947 | mutex_lock(&core->lock); | 1772 | mutex_lock(&core->lock); |
1948 | cx88_set_tvnorm(core, core->tvnorm); | 1773 | cx88_set_tvnorm(core, core->tvnorm); |
1949 | init_controls(core); | 1774 | v4l2_ctrl_handler_setup(&core->hdl); |
1950 | cx88_video_mux(core, 0); | 1775 | cx88_video_mux(core, 0); |
1951 | 1776 | ||
1952 | /* register v4l devices */ | 1777 | /* register v4l devices */ |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 8e9820cf454e..f12a77b4532d 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -115,15 +115,6 @@ struct cx8800_fmt { | |||
115 | u32 cxformat; | 115 | u32 cxformat; |
116 | }; | 116 | }; |
117 | 117 | ||
118 | struct cx88_ctrl { | ||
119 | struct v4l2_queryctrl v; | ||
120 | u32 off; | ||
121 | u32 reg; | ||
122 | u32 sreg; | ||
123 | u32 mask; | ||
124 | u32 shift; | ||
125 | }; | ||
126 | |||
127 | /* ----------------------------------------------------------- */ | 118 | /* ----------------------------------------------------------- */ |
128 | /* SRAM memory management data (see cx88-core.c) */ | 119 | /* SRAM memory management data (see cx88-core.c) */ |
129 | 120 | ||
@@ -359,6 +350,8 @@ struct cx88_core { | |||
359 | 350 | ||
360 | /* config info -- analog */ | 351 | /* config info -- analog */ |
361 | struct v4l2_device v4l2_dev; | 352 | struct v4l2_device v4l2_dev; |
353 | struct v4l2_ctrl_handler hdl; | ||
354 | struct v4l2_subdev *sd_wm8775; | ||
362 | struct i2c_client *i2c_rtc; | 355 | struct i2c_client *i2c_rtc; |
363 | unsigned int boardnr; | 356 | unsigned int boardnr; |
364 | struct cx88_board board; | 357 | struct cx88_board board; |
@@ -409,8 +402,6 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) | |||
409 | return container_of(v4l2_dev, struct cx88_core, v4l2_dev); | 402 | return container_of(v4l2_dev, struct cx88_core, v4l2_dev); |
410 | } | 403 | } |
411 | 404 | ||
412 | #define WM8775_GID (1 << 0) | ||
413 | |||
414 | #define call_hw(core, grpid, o, f, args...) \ | 405 | #define call_hw(core, grpid, o, f, args...) \ |
415 | do { \ | 406 | do { \ |
416 | if (!core->i2c_rc) { \ | 407 | if (!core->i2c_rc) { \ |
@@ -424,6 +415,36 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) | |||
424 | 415 | ||
425 | #define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) | 416 | #define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) |
426 | 417 | ||
418 | #define WM8775_GID (1 << 0) | ||
419 | |||
420 | #define wm8775_s_ctrl(core, id, val) \ | ||
421 | do { \ | ||
422 | struct v4l2_ctrl *ctrl_ = \ | ||
423 | v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \ | ||
424 | if (ctrl_ && !core->i2c_rc) { \ | ||
425 | if (core->gate_ctrl) \ | ||
426 | core->gate_ctrl(core, 1); \ | ||
427 | v4l2_ctrl_s_ctrl(ctrl_, val); \ | ||
428 | if (core->gate_ctrl) \ | ||
429 | core->gate_ctrl(core, 0); \ | ||
430 | } \ | ||
431 | } while (0) | ||
432 | |||
433 | #define wm8775_g_ctrl(core, id) \ | ||
434 | ({ \ | ||
435 | struct v4l2_ctrl *ctrl_ = \ | ||
436 | v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \ | ||
437 | s32 val = 0; \ | ||
438 | if (ctrl_ && !core->i2c_rc) { \ | ||
439 | if (core->gate_ctrl) \ | ||
440 | core->gate_ctrl(core, 1); \ | ||
441 | val = v4l2_ctrl_g_ctrl(ctrl_); \ | ||
442 | if (core->gate_ctrl) \ | ||
443 | core->gate_ctrl(core, 0); \ | ||
444 | } \ | ||
445 | val; \ | ||
446 | }) | ||
447 | |||
427 | struct cx8800_dev; | 448 | struct cx8800_dev; |
428 | struct cx8802_dev; | 449 | struct cx8802_dev; |
429 | 450 | ||
@@ -722,13 +743,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev); | |||
722 | 743 | ||
723 | /* ----------------------------------------------------------- */ | 744 | /* ----------------------------------------------------------- */ |
724 | /* cx88-video.c*/ | 745 | /* cx88-video.c*/ |
725 | extern const u32 cx88_user_ctrls[]; | ||
726 | extern int cx8800_ctrl_query(struct cx88_core *core, | ||
727 | struct v4l2_queryctrl *qctrl); | ||
728 | int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); | 746 | int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); |
729 | int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); | 747 | int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); |
730 | int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl); | ||
731 | int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl); | ||
732 | int cx88_video_mux(struct cx88_core *core, unsigned int input); | 748 | int cx88_video_mux(struct cx88_core *core, unsigned int input); |
733 | void cx88_querycap(struct file *file, struct cx88_core *core, | 749 | void cx88_querycap(struct file *file, struct cx88_core *core, |
734 | struct v4l2_capability *cap); | 750 | struct v4l2_capability *cap); |