diff options
Diffstat (limited to 'drivers/media/common')
-rw-r--r-- | drivers/media/common/saa7146_fops.c | 27 | ||||
-rw-r--r-- | drivers/media/common/saa7146_video.c | 210 |
2 files changed, 65 insertions, 172 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 | ||