aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-06-10 06:39:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-06 17:08:23 -0400
commitbac639818c2c720ea8f79f932601f9209579bf14 (patch)
tree05c6470f25f3dd1717c97949dbc9e6795f931b7d
parent902e197dcc36138e1f40f4435b7de8893ffc6c15 (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.c31
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c71
-rw-r--r--drivers/media/video/cx88/cx88-cards.c11
-rw-r--r--drivers/media/video/cx88/cx88-core.c3
-rw-r--r--drivers/media/video/cx88/cx88-video.c493
-rw-r--r--drivers/media/video/cx88/cx88.h48
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
688static const u32 *ctrl_classes[] = {
689 cx88_user_ctrls,
690 cx2341x_mpeg_ctrls,
691 NULL
692};
693
694static 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
713static 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
725static int vidioc_querycap(struct file *file, void *priv, 688static 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
920static 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
934static int vidioc_enum_input (struct file *file, void *priv, 883static 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
941static 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
949static 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
957static int vidioc_g_frequency (struct file *file, void *priv, 890static 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
1180static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { 1113static 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
164struct 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
163static const struct cx88_ctrl cx8800_ctls[] = { 180static 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};
322enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) };
323 295
324/* Must be sorted from low to high control ID! */ 296enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) };
325const 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};
340EXPORT_SYMBOL(cx88_user_ctrls);
341 297
342static const u32 * const ctrl_classes[] = {
343 cx88_user_ctrls,
344 NULL
345};
346 298
347int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl) 299int 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}
369EXPORT_SYMBOL(cx8800_ctrl_query); 303EXPORT_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
977int cx88_get_control (struct cx88_core *core, struct v4l2_control *ctl) 911static 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}
1011EXPORT_SYMBOL(cx88_get_control);
1012
1013int 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}
1105EXPORT_SYMBOL(cx88_set_control);
1106
1107static 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
1387static 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
1398static 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
1406static 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
1414static int vidioc_g_tuner (struct file *file, void *priv, 1249static 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
1566static 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
1591static void cx8800_vid_timeout(unsigned long data) 1403static 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
1602static const struct v4l2_ctrl_ops cx8800_ctrl_ops = {
1603 .s_ctrl = cx8800_s_ctrl,
1604};
1605
1796/* ----------------------------------------------------------- */ 1606/* ----------------------------------------------------------- */
1797 1607
1798static void cx8800_unregister_video(struct cx8800_dev *dev) 1608static 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
118struct 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
427struct cx8800_dev; 448struct cx8800_dev;
428struct cx8802_dev; 449struct 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*/
725extern const u32 cx88_user_ctrls[];
726extern int cx8800_ctrl_query(struct cx88_core *core,
727 struct v4l2_queryctrl *qctrl);
728int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); 746int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
729int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); 747int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f);
730int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
731int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl);
732int cx88_video_mux(struct cx88_core *core, unsigned int input); 748int cx88_video_mux(struct cx88_core *core, unsigned int input);
733void cx88_querycap(struct file *file, struct cx88_core *core, 749void cx88_querycap(struct file *file, struct cx88_core *core,
734 struct v4l2_capability *cap); 750 struct v4l2_capability *cap);