aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-04-29 15:47:47 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 13:54:58 -0400
commit6e65ca942b9664a987866ac0c62e7e450777056b (patch)
treefcd78f02819a1d3d0559ab51a8bb87412d911783 /drivers/media
parent5becbc58a01f1adaf34703c18287d9f7b46a17f6 (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')
-rw-r--r--drivers/media/common/saa7146_fops.c27
-rw-r--r--drivers/media/common/saa7146_video.c210
-rw-r--r--drivers/media/video/mxb.c173
-rw-r--r--drivers/media/video/mxb.h29
4 files changed, 150 insertions, 289 deletions
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 8d7df1a0bcd0..f14e218bed16 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -429,8 +429,13 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
429 } 429 }
430} 430}
431 431
432static const struct v4l2_ctrl_ops saa7146_ctrl_ops = {
433 .s_ctrl = saa7146_s_ctrl,
434};
435
432int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) 436int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
433{ 437{
438 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
434 struct saa7146_vv *vv; 439 struct saa7146_vv *vv;
435 int err; 440 int err;
436 441
@@ -438,9 +443,28 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
438 if (err) 443 if (err)
439 return err; 444 return err;
440 445
446 v4l2_ctrl_handler_init(hdl, 6);
447 v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
448 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
449 v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
450 V4L2_CID_CONTRAST, 0, 127, 1, 64);
451 v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
452 V4L2_CID_SATURATION, 0, 127, 1, 64);
453 v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
454 V4L2_CID_VFLIP, 0, 1, 1, 0);
455 v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
456 V4L2_CID_HFLIP, 0, 1, 1, 0);
457 if (hdl->error) {
458 err = hdl->error;
459 v4l2_ctrl_handler_free(hdl);
460 return err;
461 }
462 dev->v4l2_dev.ctrl_handler = hdl;
463
441 vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); 464 vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
442 if (vv == NULL) { 465 if (vv == NULL) {
443 ERR("out of memory. aborting.\n"); 466 ERR("out of memory. aborting.\n");
467 v4l2_ctrl_handler_free(hdl);
444 return -ENOMEM; 468 return -ENOMEM;
445 } 469 }
446 ext_vv->ops = saa7146_video_ioctl_ops; 470 ext_vv->ops = saa7146_video_ioctl_ops;
@@ -463,6 +487,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
463 if( NULL == vv->d_clipping.cpu_addr ) { 487 if( NULL == vv->d_clipping.cpu_addr ) {
464 ERR("out of memory. aborting.\n"); 488 ERR("out of memory. aborting.\n");
465 kfree(vv); 489 kfree(vv);
490 v4l2_ctrl_handler_free(hdl);
466 return -1; 491 return -1;
467 } 492 }
468 memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); 493 memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
@@ -486,6 +511,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
486 511
487 v4l2_device_unregister(&dev->v4l2_dev); 512 v4l2_device_unregister(&dev->v4l2_dev);
488 pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); 513 pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
514 v4l2_ctrl_handler_free(&dev->ctrl_handler);
489 kfree(vv); 515 kfree(vv);
490 dev->vv_data = NULL; 516 dev->vv_data = NULL;
491 dev->vv_callback = NULL; 517 dev->vv_callback = NULL;
@@ -516,6 +542,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
516 This driver needs auditing so that this flag can be removed. */ 542 This driver needs auditing so that this flag can be removed. */
517 set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags); 543 set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
518 vfd->lock = &dev->v4l2_lock; 544 vfd->lock = &dev->v4l2_lock;
545 vfd->v4l2_dev = &dev->v4l2_dev;
519 vfd->tvnorms = 0; 546 vfd->tvnorms = 0;
520 for (i = 0; i < dev->ext_vv_data->num_stds; i++) 547 for (i = 0; i < dev->ext_vv_data->num_stds; i++)
521 vfd->tvnorms |= dev->ext_vv_data->stds[i].id; 548 vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index ce30533fd972..8818e661a42f 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -202,65 +202,6 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
202EXPORT_SYMBOL_GPL(saa7146_stop_preview); 202EXPORT_SYMBOL_GPL(saa7146_stop_preview);
203 203
204/********************************************************************************/ 204/********************************************************************************/
205/* device controls */
206
207static struct v4l2_queryctrl controls[] = {
208 {
209 .id = V4L2_CID_BRIGHTNESS,
210 .name = "Brightness",
211 .minimum = 0,
212 .maximum = 255,
213 .step = 1,
214 .default_value = 128,
215 .type = V4L2_CTRL_TYPE_INTEGER,
216 .flags = V4L2_CTRL_FLAG_SLIDER,
217 },{
218 .id = V4L2_CID_CONTRAST,
219 .name = "Contrast",
220 .minimum = 0,
221 .maximum = 127,
222 .step = 1,
223 .default_value = 64,
224 .type = V4L2_CTRL_TYPE_INTEGER,
225 .flags = V4L2_CTRL_FLAG_SLIDER,
226 },{
227 .id = V4L2_CID_SATURATION,
228 .name = "Saturation",
229 .minimum = 0,
230 .maximum = 127,
231 .step = 1,
232 .default_value = 64,
233 .type = V4L2_CTRL_TYPE_INTEGER,
234 .flags = V4L2_CTRL_FLAG_SLIDER,
235 },{
236 .id = V4L2_CID_VFLIP,
237 .name = "Vertical Flip",
238 .minimum = 0,
239 .maximum = 1,
240 .type = V4L2_CTRL_TYPE_BOOLEAN,
241 },{
242 .id = V4L2_CID_HFLIP,
243 .name = "Horizontal Flip",
244 .minimum = 0,
245 .maximum = 1,
246 .type = V4L2_CTRL_TYPE_BOOLEAN,
247 },
248};
249static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl);
250
251#define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 0)
252
253static struct v4l2_queryctrl* ctrl_by_id(int id)
254{
255 int i;
256
257 for (i = 0; i < NUM_CONTROLS; i++)
258 if (controls[i].id == id)
259 return controls+i;
260 return NULL;
261}
262
263/********************************************************************************/
264/* common pagetable functions */ 205/* common pagetable functions */
265 206
266static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) 207static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
@@ -510,12 +451,13 @@ static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *
510 strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); 451 strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
511 sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci)); 452 sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
512 cap->version = SAA7146_VERSION_CODE; 453 cap->version = SAA7146_VERSION_CODE;
513 cap->capabilities = 454 cap->device_caps =
514 V4L2_CAP_VIDEO_CAPTURE | 455 V4L2_CAP_VIDEO_CAPTURE |
515 V4L2_CAP_VIDEO_OVERLAY | 456 V4L2_CAP_VIDEO_OVERLAY |
516 V4L2_CAP_READWRITE | 457 V4L2_CAP_READWRITE |
517 V4L2_CAP_STREAMING; 458 V4L2_CAP_STREAMING;
518 cap->capabilities |= dev->ext_vv_data->capabilities; 459 cap->device_caps |= dev->ext_vv_data->capabilities;
460 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
519 return 0; 461 return 0;
520} 462}
521 463
@@ -579,135 +521,58 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtd
579 return 0; 521 return 0;
580} 522}
581 523
582static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) 524int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
583{
584 const struct v4l2_queryctrl *ctrl;
585
586 if ((c->id < V4L2_CID_BASE ||
587 c->id >= V4L2_CID_LASTP1) &&
588 (c->id < V4L2_CID_PRIVATE_BASE ||
589 c->id >= V4L2_CID_PRIVATE_LASTP1))
590 return -EINVAL;
591
592 ctrl = ctrl_by_id(c->id);
593 if (ctrl == NULL)
594 return -EINVAL;
595
596 DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id);
597 *c = *ctrl;
598 return 0;
599}
600
601static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
602{ 525{
603 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 526 struct saa7146_dev *dev = container_of(ctrl->handler,
527 struct saa7146_dev, ctrl_handler);
604 struct saa7146_vv *vv = dev->vv_data; 528 struct saa7146_vv *vv = dev->vv_data;
605 const struct v4l2_queryctrl *ctrl; 529 u32 val;
606 u32 value = 0;
607 530
608 ctrl = ctrl_by_id(c->id); 531 switch (ctrl->id) {
609 if (NULL == ctrl)
610 return -EINVAL;
611 switch (c->id) {
612 case V4L2_CID_BRIGHTNESS: 532 case V4L2_CID_BRIGHTNESS:
613 value = saa7146_read(dev, BCS_CTRL); 533 val = saa7146_read(dev, BCS_CTRL);
614 c->value = 0xff & (value >> 24); 534 val &= 0x00ffffff;
615 DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value); 535 val |= (ctrl->val << 24);
616 break; 536 saa7146_write(dev, BCS_CTRL, val);
617 case V4L2_CID_CONTRAST:
618 value = saa7146_read(dev, BCS_CTRL);
619 c->value = 0x7f & (value >> 16);
620 DEB_D("V4L2_CID_CONTRAST: %d\n", c->value);
621 break;
622 case V4L2_CID_SATURATION:
623 value = saa7146_read(dev, BCS_CTRL);
624 c->value = 0x7f & (value >> 0);
625 DEB_D("V4L2_CID_SATURATION: %d\n", c->value);
626 break;
627 case V4L2_CID_VFLIP:
628 c->value = vv->vflip;
629 DEB_D("V4L2_CID_VFLIP: %d\n", c->value);
630 break;
631 case V4L2_CID_HFLIP:
632 c->value = vv->hflip;
633 DEB_D("V4L2_CID_HFLIP: %d\n", c->value);
634 break;
635 default:
636 return -EINVAL;
637 }
638 return 0;
639}
640
641static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
642{
643 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
644 struct saa7146_vv *vv = dev->vv_data;
645 const struct v4l2_queryctrl *ctrl;
646
647 ctrl = ctrl_by_id(c->id);
648 if (NULL == ctrl) {
649 DEB_D("unknown control %d\n", c->id);
650 return -EINVAL;
651 }
652
653 switch (ctrl->type) {
654 case V4L2_CTRL_TYPE_BOOLEAN:
655 case V4L2_CTRL_TYPE_MENU:
656 case V4L2_CTRL_TYPE_INTEGER:
657 if (c->value < ctrl->minimum)
658 c->value = ctrl->minimum;
659 if (c->value > ctrl->maximum)
660 c->value = ctrl->maximum;
661 break;
662 default:
663 /* nothing */;
664 }
665
666 switch (c->id) {
667 case V4L2_CID_BRIGHTNESS: {
668 u32 value = saa7146_read(dev, BCS_CTRL);
669 value &= 0x00ffffff;
670 value |= (c->value << 24);
671 saa7146_write(dev, BCS_CTRL, value);
672 saa7146_write(dev, MC2, MASK_22 | MASK_06); 537 saa7146_write(dev, MC2, MASK_22 | MASK_06);
673 break; 538 break;
674 } 539
675 case V4L2_CID_CONTRAST: { 540 case V4L2_CID_CONTRAST:
676 u32 value = saa7146_read(dev, BCS_CTRL); 541 val = saa7146_read(dev, BCS_CTRL);
677 value &= 0xff00ffff; 542 val &= 0xff00ffff;
678 value |= (c->value << 16); 543 val |= (ctrl->val << 16);
679 saa7146_write(dev, BCS_CTRL, value); 544 saa7146_write(dev, BCS_CTRL, val);
680 saa7146_write(dev, MC2, MASK_22 | MASK_06); 545 saa7146_write(dev, MC2, MASK_22 | MASK_06);
681 break; 546 break;
682 } 547
683 case V4L2_CID_SATURATION: { 548 case V4L2_CID_SATURATION:
684 u32 value = saa7146_read(dev, BCS_CTRL); 549 val = saa7146_read(dev, BCS_CTRL);
685 value &= 0xffffff00; 550 val &= 0xffffff00;
686 value |= (c->value << 0); 551 val |= (ctrl->val << 0);
687 saa7146_write(dev, BCS_CTRL, value); 552 saa7146_write(dev, BCS_CTRL, val);
688 saa7146_write(dev, MC2, MASK_22 | MASK_06); 553 saa7146_write(dev, MC2, MASK_22 | MASK_06);
689 break; 554 break;
690 } 555
691 case V4L2_CID_HFLIP: 556 case V4L2_CID_HFLIP:
692 /* fixme: we can support changing VFLIP and HFLIP here... */ 557 /* fixme: we can support changing VFLIP and HFLIP here... */
693 if (IS_CAPTURE_ACTIVE(fh) != 0) { 558 if ((vv->video_status & STATUS_CAPTURE))
694 DEB_D("V4L2_CID_HFLIP while active capture\n");
695 return -EBUSY; 559 return -EBUSY;
696 } 560 vv->hflip = ctrl->val;
697 vv->hflip = c->value;
698 break; 561 break;
562
699 case V4L2_CID_VFLIP: 563 case V4L2_CID_VFLIP:
700 if (IS_CAPTURE_ACTIVE(fh) != 0) { 564 if ((vv->video_status & STATUS_CAPTURE))
701 DEB_D("V4L2_CID_VFLIP while active capture\n");
702 return -EBUSY; 565 return -EBUSY;
703 } 566 vv->vflip = ctrl->val;
704 vv->vflip = c->value;
705 break; 567 break;
568
706 default: 569 default:
707 return -EINVAL; 570 return -EINVAL;
708 } 571 }
709 572
710 if (IS_OVERLAY_ACTIVE(fh) != 0) { 573 if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */
574 struct saa7146_fh *fh = vv->video_fh;
575
711 saa7146_stop_preview(fh); 576 saa7146_stop_preview(fh);
712 saa7146_start_preview(fh); 577 saa7146_start_preview(fh);
713 } 578 }
@@ -720,6 +585,8 @@ static int vidioc_g_parm(struct file *file, void *fh,
720 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; 585 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
721 struct saa7146_vv *vv = dev->vv_data; 586 struct saa7146_vv *vv = dev->vv_data;
722 587
588 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
589 return -EINVAL;
723 parm->parm.capture.readbuffers = 1; 590 parm->parm.capture.readbuffers = 1;
724 v4l2_video_std_frame_period(vv->standard->id, 591 v4l2_video_std_frame_period(vv->standard->id,
725 &parm->parm.capture.timeperframe); 592 &parm->parm.capture.timeperframe);
@@ -787,6 +654,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
787 } 654 }
788 655
789 f->fmt.pix.field = field; 656 f->fmt.pix.field = field;
657 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
790 if (f->fmt.pix.width > maxw) 658 if (f->fmt.pix.width > maxw)
791 f->fmt.pix.width = maxw; 659 f->fmt.pix.width = maxw;
792 if (f->fmt.pix.height > maxh) 660 if (f->fmt.pix.height > maxh)
@@ -1141,9 +1009,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
1141 .vidioc_dqbuf = vidioc_dqbuf, 1009 .vidioc_dqbuf = vidioc_dqbuf,
1142 .vidioc_g_std = vidioc_g_std, 1010 .vidioc_g_std = vidioc_g_std,
1143 .vidioc_s_std = vidioc_s_std, 1011 .vidioc_s_std = vidioc_s_std,
1144 .vidioc_queryctrl = vidioc_queryctrl,
1145 .vidioc_g_ctrl = vidioc_g_ctrl,
1146 .vidioc_s_ctrl = vidioc_s_ctrl,
1147 .vidioc_streamon = vidioc_streamon, 1012 .vidioc_streamon = vidioc_streamon,
1148 .vidioc_streamoff = vidioc_streamoff, 1013 .vidioc_streamoff = vidioc_streamoff,
1149 .vidioc_g_parm = vidioc_g_parm, 1014 .vidioc_g_parm = vidioc_g_parm,
@@ -1338,6 +1203,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
1338 fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24; 1203 fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
1339 fh->video_fmt.bytesperline = 0; 1204 fh->video_fmt.bytesperline = 0;
1340 fh->video_fmt.field = V4L2_FIELD_ANY; 1205 fh->video_fmt.field = V4L2_FIELD_ANY;
1206 fh->video_fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1341 sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); 1207 sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
1342 fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; 1208 fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
1343 1209
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 };
64static struct v4l2_input mxb_inputs[MXB_INPUTS] = { 64static 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 */
95static 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. */
95static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { 125static 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
118static struct v4l2_queryctrl mxb_controls[] = {
119 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
120};
121
122struct mxb 147struct 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
169static struct saa7146_extension extension; 194static struct saa7146_extension extension;
170 195
196static 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
215static const struct v4l2_ctrl_ops mxb_ctrl_ops = {
216 .s_ctrl = mxb_s_ctrl,
217};
218
171static int mxb_probe(struct saa7146_dev *dev) 219static 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
388static 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
403static 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
427static 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
451static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) 442static 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
601static 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
615static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) 609static 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
630static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) 624static 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
837static struct saa7146_ext_vv vv_data = { 834static 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 */
15static 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