diff options
| author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-04-29 15:47:47 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-14 13:54:58 -0400 |
| commit | 6e65ca942b9664a987866ac0c62e7e450777056b (patch) | |
| tree | fcd78f02819a1d3d0559ab51a8bb87412d911783 /drivers/media/video/mxb.c | |
| parent | 5becbc58a01f1adaf34703c18287d9f7b46a17f6 (diff) | |
[media] mxb/saa7146: first round of cleanups
Convert to the control framework, fix the easy v4l2-compliance failures.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mxb.c')
| -rw-r--r-- | drivers/media/video/mxb.c | 173 |
1 files changed, 85 insertions, 88 deletions
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index ca3f70f0bad..2bed92ff947 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, |
