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 | |
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')
-rw-r--r-- | drivers/media/common/saa7146_fops.c | 27 | ||||
-rw-r--r-- | drivers/media/common/saa7146_video.c | 210 | ||||
-rw-r--r-- | drivers/media/video/mxb.c | 173 | ||||
-rw-r--r-- | drivers/media/video/mxb.h | 29 |
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 | ||
432 | static const struct v4l2_ctrl_ops saa7146_ctrl_ops = { | ||
433 | .s_ctrl = saa7146_s_ctrl, | ||
434 | }; | ||
435 | |||
432 | int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) | 436 | int 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) | |||
202 | EXPORT_SYMBOL_GPL(saa7146_stop_preview); | 202 | EXPORT_SYMBOL_GPL(saa7146_stop_preview); |
203 | 203 | ||
204 | /********************************************************************************/ | 204 | /********************************************************************************/ |
205 | /* device controls */ | ||
206 | |||
207 | static 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 | }; | ||
249 | static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl); | ||
250 | |||
251 | #define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 0) | ||
252 | |||
253 | static 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 | ||
266 | static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) | 207 | static 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 | ||
582 | static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c) | 524 | int 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 | |||
601 | static 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 | |||
641 | static 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 }; | |||
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 |