diff options
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/mxb.c | 173 | ||||
-rw-r--r-- | drivers/media/video/mxb.h | 29 |
2 files changed, 85 insertions, 117 deletions
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index ca3f70f0bad5..2bed92ff9476 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -64,8 +64,8 @@ enum { TUNER, AUX1, AUX3, AUX3_YC }; | |||
64 | static struct v4l2_input mxb_inputs[MXB_INPUTS] = { | 64 | static struct v4l2_input mxb_inputs[MXB_INPUTS] = { |
65 | { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, | 65 | { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, |
66 | { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, | 66 | { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, |
67 | { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, | 67 | { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, |
68 | { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, | 68 | { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD }, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | /* this array holds the information, which port of the saa7146 each | 71 | /* this array holds the information, which port of the saa7146 each |
@@ -90,6 +90,36 @@ struct mxb_routing { | |||
90 | u32 output; | 90 | u32 output; |
91 | }; | 91 | }; |
92 | 92 | ||
93 | /* these are the available audio sources, which can switched | ||
94 | to the line- and cd-output individually */ | ||
95 | static struct v4l2_audio mxb_audios[MXB_AUDIOS] = { | ||
96 | { | ||
97 | .index = 0, | ||
98 | .name = "Tuner", | ||
99 | .capability = V4L2_AUDCAP_STEREO, | ||
100 | } , { | ||
101 | .index = 1, | ||
102 | .name = "AUX1", | ||
103 | .capability = V4L2_AUDCAP_STEREO, | ||
104 | } , { | ||
105 | .index = 2, | ||
106 | .name = "AUX2", | ||
107 | .capability = V4L2_AUDCAP_STEREO, | ||
108 | } , { | ||
109 | .index = 3, | ||
110 | .name = "AUX3", | ||
111 | .capability = V4L2_AUDCAP_STEREO, | ||
112 | } , { | ||
113 | .index = 4, | ||
114 | .name = "Radio (X9)", | ||
115 | .capability = V4L2_AUDCAP_STEREO, | ||
116 | } , { | ||
117 | .index = 5, | ||
118 | .name = "CD-ROM (X10)", | ||
119 | .capability = V4L2_AUDCAP_STEREO, | ||
120 | } | ||
121 | }; | ||
122 | |||
93 | /* These are the necessary input-output-pins for bringing one audio source | 123 | /* These are the necessary input-output-pins for bringing one audio source |
94 | (see above) to the CD-output. Note that gain is set to 0 in this table. */ | 124 | (see above) to the CD-output. Note that gain is set to 0 in this table. */ |
95 | static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { | 125 | static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { |
@@ -114,11 +144,6 @@ static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = { | |||
114 | { { 6, 3 }, { 6, 2 } } /* Mute */ | 144 | { { 6, 3 }, { 6, 2 } } /* Mute */ |
115 | }; | 145 | }; |
116 | 146 | ||
117 | #define MAXCONTROLS 1 | ||
118 | static struct v4l2_queryctrl mxb_controls[] = { | ||
119 | { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 }, | ||
120 | }; | ||
121 | |||
122 | struct mxb | 147 | struct mxb |
123 | { | 148 | { |
124 | struct video_device *video_dev; | 149 | struct video_device *video_dev; |
@@ -168,16 +193,45 @@ static inline void tea6420_route_line(struct mxb *mxb, int idx) | |||
168 | 193 | ||
169 | static struct saa7146_extension extension; | 194 | static struct saa7146_extension extension; |
170 | 195 | ||
196 | static int mxb_s_ctrl(struct v4l2_ctrl *ctrl) | ||
197 | { | ||
198 | struct saa7146_dev *dev = container_of(ctrl->handler, | ||
199 | struct saa7146_dev, ctrl_handler); | ||
200 | struct mxb *mxb = dev->ext_priv; | ||
201 | |||
202 | switch (ctrl->id) { | ||
203 | case V4L2_CID_AUDIO_MUTE: | ||
204 | mxb->cur_mute = ctrl->val; | ||
205 | /* switch the audio-source */ | ||
206 | tea6420_route_line(mxb, ctrl->val ? 6 : | ||
207 | video_audio_connect[mxb->cur_input]); | ||
208 | break; | ||
209 | default: | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static const struct v4l2_ctrl_ops mxb_ctrl_ops = { | ||
216 | .s_ctrl = mxb_s_ctrl, | ||
217 | }; | ||
218 | |||
171 | static int mxb_probe(struct saa7146_dev *dev) | 219 | static int mxb_probe(struct saa7146_dev *dev) |
172 | { | 220 | { |
221 | struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; | ||
173 | struct mxb *mxb = NULL; | 222 | struct mxb *mxb = NULL; |
174 | 223 | ||
224 | v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops, | ||
225 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); | ||
226 | if (hdl->error) | ||
227 | return hdl->error; | ||
175 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); | 228 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); |
176 | if (mxb == NULL) { | 229 | if (mxb == NULL) { |
177 | DEB_D("not enough kernel memory\n"); | 230 | DEB_D("not enough kernel memory\n"); |
178 | return -ENOMEM; | 231 | return -ENOMEM; |
179 | } | 232 | } |
180 | 233 | ||
234 | |||
181 | snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); | 235 | snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); |
182 | 236 | ||
183 | saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); | 237 | saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); |
@@ -385,69 +439,6 @@ void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) | |||
385 | } | 439 | } |
386 | */ | 440 | */ |
387 | 441 | ||
388 | static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc) | ||
389 | { | ||
390 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
391 | int i; | ||
392 | |||
393 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | ||
394 | if (mxb_controls[i].id == qc->id) { | ||
395 | *qc = mxb_controls[i]; | ||
396 | DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id); | ||
397 | return 0; | ||
398 | } | ||
399 | } | ||
400 | return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc); | ||
401 | } | ||
402 | |||
403 | static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc) | ||
404 | { | ||
405 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
406 | struct mxb *mxb = (struct mxb *)dev->ext_priv; | ||
407 | int i; | ||
408 | |||
409 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | ||
410 | if (mxb_controls[i].id == vc->id) | ||
411 | break; | ||
412 | } | ||
413 | |||
414 | if (i < 0) | ||
415 | return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc); | ||
416 | |||
417 | if (vc->id == V4L2_CID_AUDIO_MUTE) { | ||
418 | vc->value = mxb->cur_mute; | ||
419 | DEB_D("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value); | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | DEB_EE("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value); | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) | ||
428 | { | ||
429 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
430 | struct mxb *mxb = (struct mxb *)dev->ext_priv; | ||
431 | int i = 0; | ||
432 | |||
433 | for (i = MAXCONTROLS - 1; i >= 0; i--) { | ||
434 | if (mxb_controls[i].id == vc->id) | ||
435 | break; | ||
436 | } | ||
437 | |||
438 | if (i < 0) | ||
439 | return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc); | ||
440 | |||
441 | if (vc->id == V4L2_CID_AUDIO_MUTE) { | ||
442 | mxb->cur_mute = vc->value; | ||
443 | /* switch the audio-source */ | ||
444 | tea6420_route_line(mxb, vc->value ? 6 : | ||
445 | video_audio_connect[mxb->cur_input]); | ||
446 | DEB_EE("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d\n", vc->value); | ||
447 | } | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) | 442 | static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) |
452 | { | 443 | { |
453 | DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index); | 444 | DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index); |
@@ -568,12 +559,8 @@ static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency | |||
568 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | 559 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; |
569 | struct mxb *mxb = (struct mxb *)dev->ext_priv; | 560 | struct mxb *mxb = (struct mxb *)dev->ext_priv; |
570 | 561 | ||
571 | if (mxb->cur_input) { | 562 | if (f->tuner) |
572 | DEB_D("VIDIOC_G_FREQ: channel %d does not have a tuner!\n", | ||
573 | mxb->cur_input); | ||
574 | return -EINVAL; | 563 | return -EINVAL; |
575 | } | ||
576 | |||
577 | *f = mxb->cur_freq; | 564 | *f = mxb->cur_freq; |
578 | 565 | ||
579 | DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency); | 566 | DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency); |
@@ -592,17 +579,16 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency | |||
592 | if (V4L2_TUNER_ANALOG_TV != f->type) | 579 | if (V4L2_TUNER_ANALOG_TV != f->type) |
593 | return -EINVAL; | 580 | return -EINVAL; |
594 | 581 | ||
595 | if (mxb->cur_input) { | ||
596 | DEB_D("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", | ||
597 | mxb->cur_input); | ||
598 | return -EINVAL; | ||
599 | } | ||
600 | |||
601 | mxb->cur_freq = *f; | ||
602 | DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency); | 582 | DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency); |
603 | 583 | ||
604 | /* tune in desired frequency */ | 584 | /* tune in desired frequency */ |
605 | tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); | 585 | tuner_call(mxb, tuner, s_frequency, f); |
586 | /* let the tuner subdev clamp the frequency to the tuner range */ | ||
587 | tuner_call(mxb, tuner, g_frequency, f); | ||
588 | mxb->cur_freq = *f; | ||
589 | |||
590 | if (mxb->cur_input) | ||
591 | return 0; | ||
606 | 592 | ||
607 | /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ | 593 | /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ |
608 | spin_lock(&dev->slock); | 594 | spin_lock(&dev->slock); |
@@ -612,6 +598,14 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency | |||
612 | return 0; | 598 | return 0; |
613 | } | 599 | } |
614 | 600 | ||
601 | static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) | ||
602 | { | ||
603 | if (a->index >= MXB_AUDIOS) | ||
604 | return -EINVAL; | ||
605 | *a = mxb_audios[a->index]; | ||
606 | return 0; | ||
607 | } | ||
608 | |||
615 | static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) | 609 | static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) |
616 | { | 610 | { |
617 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | 611 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; |
@@ -629,8 +623,13 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) | |||
629 | 623 | ||
630 | static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) | 624 | static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) |
631 | { | 625 | { |
626 | struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; | ||
627 | struct mxb *mxb = (struct mxb *)dev->ext_priv; | ||
628 | |||
632 | DEB_D("VIDIOC_S_AUDIO %d\n", a->index); | 629 | DEB_D("VIDIOC_S_AUDIO %d\n", a->index); |
633 | return 0; | 630 | if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) |
631 | return 0; | ||
632 | return -EINVAL; | ||
634 | } | 633 | } |
635 | 634 | ||
636 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 635 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -709,9 +708,6 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data | |||
709 | } | 708 | } |
710 | mxb = (struct mxb *)dev->ext_priv; | 709 | mxb = (struct mxb *)dev->ext_priv; |
711 | 710 | ||
712 | vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; | ||
713 | vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; | ||
714 | vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; | ||
715 | vv_data.ops.vidioc_enum_input = vidioc_enum_input; | 711 | vv_data.ops.vidioc_enum_input = vidioc_enum_input; |
716 | vv_data.ops.vidioc_g_input = vidioc_g_input; | 712 | vv_data.ops.vidioc_g_input = vidioc_g_input; |
717 | vv_data.ops.vidioc_s_input = vidioc_s_input; | 713 | vv_data.ops.vidioc_s_input = vidioc_s_input; |
@@ -719,6 +715,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data | |||
719 | vv_data.ops.vidioc_s_tuner = vidioc_s_tuner; | 715 | vv_data.ops.vidioc_s_tuner = vidioc_s_tuner; |
720 | vv_data.ops.vidioc_g_frequency = vidioc_g_frequency; | 716 | vv_data.ops.vidioc_g_frequency = vidioc_g_frequency; |
721 | vv_data.ops.vidioc_s_frequency = vidioc_s_frequency; | 717 | vv_data.ops.vidioc_s_frequency = vidioc_s_frequency; |
718 | vv_data.ops.vidioc_enumaudio = vidioc_enumaudio; | ||
722 | vv_data.ops.vidioc_g_audio = vidioc_g_audio; | 719 | vv_data.ops.vidioc_g_audio = vidioc_g_audio; |
723 | vv_data.ops.vidioc_s_audio = vidioc_s_audio; | 720 | vv_data.ops.vidioc_s_audio = vidioc_s_audio; |
724 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 721 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -836,7 +833,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); | |||
836 | 833 | ||
837 | static struct saa7146_ext_vv vv_data = { | 834 | static struct saa7146_ext_vv vv_data = { |
838 | .inputs = MXB_INPUTS, | 835 | .inputs = MXB_INPUTS, |
839 | .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, | 836 | .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO, |
840 | .stds = &standard[0], | 837 | .stds = &standard[0], |
841 | .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), | 838 | .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), |
842 | .std_callback = &std_callback, | 839 | .std_callback = &std_callback, |
diff --git a/drivers/media/video/mxb.h b/drivers/media/video/mxb.h index 400a57ba62ec..dfa4b1cca23a 100644 --- a/drivers/media/video/mxb.h +++ b/drivers/media/video/mxb.h | |||
@@ -10,33 +10,4 @@ | |||
10 | 10 | ||
11 | #define MXB_AUDIOS 6 | 11 | #define MXB_AUDIOS 6 |
12 | 12 | ||
13 | /* these are the available audio sources, which can switched | ||
14 | to the line- and cd-output individually */ | ||
15 | static struct v4l2_audio mxb_audios[MXB_AUDIOS] = { | ||
16 | { | ||
17 | .index = 0, | ||
18 | .name = "Tuner", | ||
19 | .capability = V4L2_AUDCAP_STEREO, | ||
20 | } , { | ||
21 | .index = 1, | ||
22 | .name = "AUX1", | ||
23 | .capability = V4L2_AUDCAP_STEREO, | ||
24 | } , { | ||
25 | .index = 2, | ||
26 | .name = "AUX2", | ||
27 | .capability = V4L2_AUDCAP_STEREO, | ||
28 | } , { | ||
29 | .index = 3, | ||
30 | .name = "AUX3", | ||
31 | .capability = V4L2_AUDCAP_STEREO, | ||
32 | } , { | ||
33 | .index = 4, | ||
34 | .name = "Radio (X9)", | ||
35 | .capability = V4L2_AUDCAP_STEREO, | ||
36 | } , { | ||
37 | .index = 5, | ||
38 | .name = "CD-ROM (X10)", | ||
39 | .capability = V4L2_AUDCAP_STEREO, | ||
40 | } | ||
41 | }; | ||
42 | #endif | 13 | #endif |