diff options
Diffstat (limited to 'drivers/media/video/au0828/au0828-video.c')
-rw-r--r-- | drivers/media/video/au0828/au0828-video.c | 443 |
1 files changed, 327 insertions, 116 deletions
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 52f25aabb6dc..7989a7ba7c40 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c | |||
@@ -314,6 +314,23 @@ static inline void buffer_filled(struct au0828_dev *dev, | |||
314 | wake_up(&buf->vb.done); | 314 | wake_up(&buf->vb.done); |
315 | } | 315 | } |
316 | 316 | ||
317 | static inline void vbi_buffer_filled(struct au0828_dev *dev, | ||
318 | struct au0828_dmaqueue *dma_q, | ||
319 | struct au0828_buffer *buf) | ||
320 | { | ||
321 | /* Advice that buffer was filled */ | ||
322 | au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i); | ||
323 | |||
324 | buf->vb.state = VIDEOBUF_DONE; | ||
325 | buf->vb.field_count++; | ||
326 | do_gettimeofday(&buf->vb.ts); | ||
327 | |||
328 | dev->isoc_ctl.vbi_buf = NULL; | ||
329 | |||
330 | list_del(&buf->vb.queue); | ||
331 | wake_up(&buf->vb.done); | ||
332 | } | ||
333 | |||
317 | /* | 334 | /* |
318 | * Identify the buffer header type and properly handles | 335 | * Identify the buffer header type and properly handles |
319 | */ | 336 | */ |
@@ -327,6 +344,9 @@ static void au0828_copy_video(struct au0828_dev *dev, | |||
327 | int linesdone, currlinedone, offset, lencopy, remain; | 344 | int linesdone, currlinedone, offset, lencopy, remain; |
328 | int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ | 345 | int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */ |
329 | 346 | ||
347 | if (len == 0) | ||
348 | return; | ||
349 | |||
330 | if (dma_q->pos + len > buf->vb.size) | 350 | if (dma_q->pos + len > buf->vb.size) |
331 | len = buf->vb.size - dma_q->pos; | 351 | len = buf->vb.size - dma_q->pos; |
332 | 352 | ||
@@ -414,17 +434,98 @@ static inline void get_next_buf(struct au0828_dmaqueue *dma_q, | |||
414 | return; | 434 | return; |
415 | } | 435 | } |
416 | 436 | ||
437 | static void au0828_copy_vbi(struct au0828_dev *dev, | ||
438 | struct au0828_dmaqueue *dma_q, | ||
439 | struct au0828_buffer *buf, | ||
440 | unsigned char *p, | ||
441 | unsigned char *outp, unsigned long len) | ||
442 | { | ||
443 | unsigned char *startwrite, *startread; | ||
444 | int bytesperline; | ||
445 | int i, j = 0; | ||
446 | |||
447 | if (dev == NULL) { | ||
448 | au0828_isocdbg("dev is null\n"); | ||
449 | return; | ||
450 | } | ||
451 | |||
452 | if (dma_q == NULL) { | ||
453 | au0828_isocdbg("dma_q is null\n"); | ||
454 | return; | ||
455 | } | ||
456 | if (buf == NULL) | ||
457 | return; | ||
458 | if (p == NULL) { | ||
459 | au0828_isocdbg("p is null\n"); | ||
460 | return; | ||
461 | } | ||
462 | if (outp == NULL) { | ||
463 | au0828_isocdbg("outp is null\n"); | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | bytesperline = dev->vbi_width; | ||
468 | |||
469 | if (dma_q->pos + len > buf->vb.size) | ||
470 | len = buf->vb.size - dma_q->pos; | ||
471 | |||
472 | startread = p; | ||
473 | startwrite = outp + (dma_q->pos / 2); | ||
474 | |||
475 | /* Make sure the bottom field populates the second half of the frame */ | ||
476 | if (buf->top_field == 0) | ||
477 | startwrite += bytesperline * dev->vbi_height; | ||
478 | |||
479 | for (i = 0; i < len; i += 2) | ||
480 | startwrite[j++] = startread[i+1]; | ||
481 | |||
482 | dma_q->pos += len; | ||
483 | } | ||
484 | |||
485 | |||
486 | /* | ||
487 | * video-buf generic routine to get the next available VBI buffer | ||
488 | */ | ||
489 | static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q, | ||
490 | struct au0828_buffer **buf) | ||
491 | { | ||
492 | struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq); | ||
493 | char *outp; | ||
494 | |||
495 | if (list_empty(&dma_q->active)) { | ||
496 | au0828_isocdbg("No active queue to serve\n"); | ||
497 | dev->isoc_ctl.vbi_buf = NULL; | ||
498 | *buf = NULL; | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | /* Get the next buffer */ | ||
503 | *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue); | ||
504 | /* Cleans up buffer - Usefull for testing for frame/URB loss */ | ||
505 | outp = videobuf_to_vmalloc(&(*buf)->vb); | ||
506 | memset(outp, 0x00, (*buf)->vb.size); | ||
507 | |||
508 | dev->isoc_ctl.vbi_buf = *buf; | ||
509 | |||
510 | return; | ||
511 | } | ||
512 | |||
417 | /* | 513 | /* |
418 | * Controls the isoc copy of each urb packet | 514 | * Controls the isoc copy of each urb packet |
419 | */ | 515 | */ |
420 | static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | 516 | static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) |
421 | { | 517 | { |
422 | struct au0828_buffer *buf; | 518 | struct au0828_buffer *buf; |
519 | struct au0828_buffer *vbi_buf; | ||
423 | struct au0828_dmaqueue *dma_q = urb->context; | 520 | struct au0828_dmaqueue *dma_q = urb->context; |
521 | struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq; | ||
424 | unsigned char *outp = NULL; | 522 | unsigned char *outp = NULL; |
523 | unsigned char *vbioutp = NULL; | ||
425 | int i, len = 0, rc = 1; | 524 | int i, len = 0, rc = 1; |
426 | unsigned char *p; | 525 | unsigned char *p; |
427 | unsigned char fbyte; | 526 | unsigned char fbyte; |
527 | unsigned int vbi_field_size; | ||
528 | unsigned int remain, lencopy; | ||
428 | 529 | ||
429 | if (!dev) | 530 | if (!dev) |
430 | return 0; | 531 | return 0; |
@@ -443,6 +544,10 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | |||
443 | if (buf != NULL) | 544 | if (buf != NULL) |
444 | outp = videobuf_to_vmalloc(&buf->vb); | 545 | outp = videobuf_to_vmalloc(&buf->vb); |
445 | 546 | ||
547 | vbi_buf = dev->isoc_ctl.vbi_buf; | ||
548 | if (vbi_buf != NULL) | ||
549 | vbioutp = videobuf_to_vmalloc(&vbi_buf->vb); | ||
550 | |||
446 | for (i = 0; i < urb->number_of_packets; i++) { | 551 | for (i = 0; i < urb->number_of_packets; i++) { |
447 | int status = urb->iso_frame_desc[i].status; | 552 | int status = urb->iso_frame_desc[i].status; |
448 | 553 | ||
@@ -472,6 +577,19 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | |||
472 | au0828_isocdbg("Video frame %s\n", | 577 | au0828_isocdbg("Video frame %s\n", |
473 | (fbyte & 0x40) ? "odd" : "even"); | 578 | (fbyte & 0x40) ? "odd" : "even"); |
474 | if (!(fbyte & 0x40)) { | 579 | if (!(fbyte & 0x40)) { |
580 | /* VBI */ | ||
581 | if (vbi_buf != NULL) | ||
582 | vbi_buffer_filled(dev, | ||
583 | vbi_dma_q, | ||
584 | vbi_buf); | ||
585 | vbi_get_next_buf(vbi_dma_q, &vbi_buf); | ||
586 | if (vbi_buf == NULL) | ||
587 | vbioutp = NULL; | ||
588 | else | ||
589 | vbioutp = videobuf_to_vmalloc( | ||
590 | &vbi_buf->vb); | ||
591 | |||
592 | /* Video */ | ||
475 | if (buf != NULL) | 593 | if (buf != NULL) |
476 | buffer_filled(dev, dma_q, buf); | 594 | buffer_filled(dev, dma_q, buf); |
477 | get_next_buf(dma_q, &buf); | 595 | get_next_buf(dma_q, &buf); |
@@ -488,9 +606,36 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) | |||
488 | buf->top_field = 0; | 606 | buf->top_field = 0; |
489 | } | 607 | } |
490 | 608 | ||
609 | if (vbi_buf != NULL) { | ||
610 | if (fbyte & 0x40) | ||
611 | vbi_buf->top_field = 1; | ||
612 | else | ||
613 | vbi_buf->top_field = 0; | ||
614 | } | ||
615 | |||
616 | dev->vbi_read = 0; | ||
617 | vbi_dma_q->pos = 0; | ||
491 | dma_q->pos = 0; | 618 | dma_q->pos = 0; |
492 | } | 619 | } |
493 | if (buf != NULL) | 620 | |
621 | vbi_field_size = dev->vbi_width * dev->vbi_height * 2; | ||
622 | if (dev->vbi_read < vbi_field_size) { | ||
623 | remain = vbi_field_size - dev->vbi_read; | ||
624 | if (len < remain) | ||
625 | lencopy = len; | ||
626 | else | ||
627 | lencopy = remain; | ||
628 | |||
629 | if (vbi_buf != NULL) | ||
630 | au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p, | ||
631 | vbioutp, len); | ||
632 | |||
633 | len -= lencopy; | ||
634 | p += lencopy; | ||
635 | dev->vbi_read += lencopy; | ||
636 | } | ||
637 | |||
638 | if (dev->vbi_read >= vbi_field_size && buf != NULL) | ||
494 | au0828_copy_video(dev, dma_q, buf, p, outp, len); | 639 | au0828_copy_video(dev, dma_q, buf, p, outp, len); |
495 | } | 640 | } |
496 | return rc; | 641 | return rc; |
@@ -642,7 +787,7 @@ int au0828_analog_stream_enable(struct au0828_dev *d) | |||
642 | au0828_writereg(d, 0x114, 0xa0); | 787 | au0828_writereg(d, 0x114, 0xa0); |
643 | au0828_writereg(d, 0x115, 0x05); | 788 | au0828_writereg(d, 0x115, 0x05); |
644 | /* set y position */ | 789 | /* set y position */ |
645 | au0828_writereg(d, 0x112, 0x02); | 790 | au0828_writereg(d, 0x112, 0x00); |
646 | au0828_writereg(d, 0x113, 0x00); | 791 | au0828_writereg(d, 0x113, 0x00); |
647 | au0828_writereg(d, 0x116, 0xf2); | 792 | au0828_writereg(d, 0x116, 0xf2); |
648 | au0828_writereg(d, 0x117, 0x00); | 793 | au0828_writereg(d, 0x117, 0x00); |
@@ -703,47 +848,83 @@ void au0828_analog_unregister(struct au0828_dev *dev) | |||
703 | 848 | ||
704 | 849 | ||
705 | /* Usage lock check functions */ | 850 | /* Usage lock check functions */ |
706 | static int res_get(struct au0828_fh *fh) | 851 | static int res_get(struct au0828_fh *fh, unsigned int bit) |
707 | { | 852 | { |
708 | struct au0828_dev *dev = fh->dev; | 853 | struct au0828_dev *dev = fh->dev; |
709 | int rc = 0; | ||
710 | 854 | ||
711 | /* This instance already has stream_on */ | 855 | if (fh->resources & bit) |
712 | if (fh->stream_on) | 856 | /* have it already allocated */ |
713 | return rc; | 857 | return 1; |
714 | 858 | ||
715 | if (dev->stream_on) | 859 | /* is it free? */ |
716 | return -EBUSY; | 860 | mutex_lock(&dev->lock); |
861 | if (dev->resources & bit) { | ||
862 | /* no, someone else uses it */ | ||
863 | mutex_unlock(&dev->lock); | ||
864 | return 0; | ||
865 | } | ||
866 | /* it's free, grab it */ | ||
867 | fh->resources |= bit; | ||
868 | dev->resources |= bit; | ||
869 | dprintk(1, "res: get %d\n", bit); | ||
870 | mutex_unlock(&dev->lock); | ||
871 | return 1; | ||
872 | } | ||
717 | 873 | ||
718 | dev->stream_on = 1; | 874 | static int res_check(struct au0828_fh *fh, unsigned int bit) |
719 | fh->stream_on = 1; | 875 | { |
720 | return rc; | 876 | return fh->resources & bit; |
721 | } | 877 | } |
722 | 878 | ||
723 | static int res_check(struct au0828_fh *fh) | 879 | static int res_locked(struct au0828_dev *dev, unsigned int bit) |
724 | { | 880 | { |
725 | return fh->stream_on; | 881 | return dev->resources & bit; |
726 | } | 882 | } |
727 | 883 | ||
728 | static void res_free(struct au0828_fh *fh) | 884 | static void res_free(struct au0828_fh *fh, unsigned int bits) |
729 | { | 885 | { |
730 | struct au0828_dev *dev = fh->dev; | 886 | struct au0828_dev *dev = fh->dev; |
731 | 887 | ||
732 | fh->stream_on = 0; | 888 | BUG_ON((fh->resources & bits) != bits); |
733 | dev->stream_on = 0; | 889 | |
890 | mutex_lock(&dev->lock); | ||
891 | fh->resources &= ~bits; | ||
892 | dev->resources &= ~bits; | ||
893 | dprintk(1, "res: put %d\n", bits); | ||
894 | mutex_unlock(&dev->lock); | ||
895 | } | ||
896 | |||
897 | static int get_ressource(struct au0828_fh *fh) | ||
898 | { | ||
899 | switch (fh->type) { | ||
900 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
901 | return AU0828_RESOURCE_VIDEO; | ||
902 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
903 | return AU0828_RESOURCE_VBI; | ||
904 | default: | ||
905 | BUG(); | ||
906 | return 0; | ||
907 | } | ||
734 | } | 908 | } |
735 | 909 | ||
736 | static int au0828_v4l2_open(struct file *filp) | 910 | static int au0828_v4l2_open(struct file *filp) |
737 | { | 911 | { |
738 | int ret = 0; | 912 | int ret = 0; |
913 | struct video_device *vdev = video_devdata(filp); | ||
739 | struct au0828_dev *dev = video_drvdata(filp); | 914 | struct au0828_dev *dev = video_drvdata(filp); |
740 | struct au0828_fh *fh; | 915 | struct au0828_fh *fh; |
741 | int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 916 | int type; |
742 | 917 | ||
743 | #ifdef VBI_IS_WORKING | 918 | switch (vdev->vfl_type) { |
744 | if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER) | 919 | case VFL_TYPE_GRABBER: |
920 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
921 | break; | ||
922 | case VFL_TYPE_VBI: | ||
745 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | 923 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
746 | #endif | 924 | break; |
925 | default: | ||
926 | return -EINVAL; | ||
927 | } | ||
747 | 928 | ||
748 | fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); | 929 | fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); |
749 | if (NULL == fh) { | 930 | if (NULL == fh) { |
@@ -781,10 +962,21 @@ static int au0828_v4l2_open(struct file *filp) | |||
781 | dev->users++; | 962 | dev->users++; |
782 | 963 | ||
783 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, | 964 | videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops, |
784 | NULL, &dev->slock, fh->type, | 965 | NULL, &dev->slock, |
966 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
785 | V4L2_FIELD_INTERLACED, | 967 | V4L2_FIELD_INTERLACED, |
786 | sizeof(struct au0828_buffer), fh); | 968 | sizeof(struct au0828_buffer), fh); |
787 | 969 | ||
970 | /* VBI Setup */ | ||
971 | dev->vbi_width = 720; | ||
972 | dev->vbi_height = 1; | ||
973 | videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops, | ||
974 | NULL, &dev->slock, | ||
975 | V4L2_BUF_TYPE_VBI_CAPTURE, | ||
976 | V4L2_FIELD_SEQ_TB, | ||
977 | sizeof(struct au0828_buffer), fh); | ||
978 | |||
979 | |||
788 | return ret; | 980 | return ret; |
789 | } | 981 | } |
790 | 982 | ||
@@ -794,17 +986,19 @@ static int au0828_v4l2_close(struct file *filp) | |||
794 | struct au0828_fh *fh = filp->private_data; | 986 | struct au0828_fh *fh = filp->private_data; |
795 | struct au0828_dev *dev = fh->dev; | 987 | struct au0828_dev *dev = fh->dev; |
796 | 988 | ||
797 | mutex_lock(&dev->lock); | 989 | if (res_check(fh, AU0828_RESOURCE_VIDEO)) { |
798 | if (res_check(fh)) | ||
799 | res_free(fh); | ||
800 | |||
801 | if (dev->users == 1) { | ||
802 | videobuf_stop(&fh->vb_vidq); | 990 | videobuf_stop(&fh->vb_vidq); |
803 | videobuf_mmap_free(&fh->vb_vidq); | 991 | res_free(fh, AU0828_RESOURCE_VIDEO); |
992 | } | ||
993 | |||
994 | if (res_check(fh, AU0828_RESOURCE_VBI)) { | ||
995 | videobuf_stop(&fh->vb_vbiq); | ||
996 | res_free(fh, AU0828_RESOURCE_VBI); | ||
997 | } | ||
804 | 998 | ||
999 | if (dev->users == 1) { | ||
805 | if (dev->dev_state & DEV_DISCONNECTED) { | 1000 | if (dev->dev_state & DEV_DISCONNECTED) { |
806 | au0828_analog_unregister(dev); | 1001 | au0828_analog_unregister(dev); |
807 | mutex_unlock(&dev->lock); | ||
808 | kfree(dev); | 1002 | kfree(dev); |
809 | return 0; | 1003 | return 0; |
810 | } | 1004 | } |
@@ -823,10 +1017,11 @@ static int au0828_v4l2_close(struct file *filp) | |||
823 | printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); | 1017 | printk(KERN_INFO "Au0828 can't set alternate to 0!\n"); |
824 | } | 1018 | } |
825 | 1019 | ||
1020 | videobuf_mmap_free(&fh->vb_vidq); | ||
1021 | videobuf_mmap_free(&fh->vb_vbiq); | ||
826 | kfree(fh); | 1022 | kfree(fh); |
827 | dev->users--; | 1023 | dev->users--; |
828 | wake_up_interruptible_nr(&dev->open, 1); | 1024 | wake_up_interruptible_nr(&dev->open, 1); |
829 | mutex_unlock(&dev->lock); | ||
830 | return 0; | 1025 | return 0; |
831 | } | 1026 | } |
832 | 1027 | ||
@@ -842,16 +1037,21 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf, | |||
842 | return rc; | 1037 | return rc; |
843 | 1038 | ||
844 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1039 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
845 | mutex_lock(&dev->lock); | 1040 | if (res_locked(dev, AU0828_RESOURCE_VIDEO)) |
846 | rc = res_get(fh); | 1041 | return -EBUSY; |
847 | mutex_unlock(&dev->lock); | ||
848 | |||
849 | if (unlikely(rc < 0)) | ||
850 | return rc; | ||
851 | 1042 | ||
852 | return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, | 1043 | return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, |
853 | filp->f_flags & O_NONBLOCK); | 1044 | filp->f_flags & O_NONBLOCK); |
854 | } | 1045 | } |
1046 | |||
1047 | if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
1048 | if (!res_get(fh, AU0828_RESOURCE_VBI)) | ||
1049 | return -EBUSY; | ||
1050 | |||
1051 | return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, | ||
1052 | filp->f_flags & O_NONBLOCK); | ||
1053 | } | ||
1054 | |||
855 | return 0; | 1055 | return 0; |
856 | } | 1056 | } |
857 | 1057 | ||
@@ -865,17 +1065,17 @@ static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait) | |||
865 | if (rc < 0) | 1065 | if (rc < 0) |
866 | return rc; | 1066 | return rc; |
867 | 1067 | ||
868 | mutex_lock(&dev->lock); | 1068 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
869 | rc = res_get(fh); | 1069 | if (!res_get(fh, AU0828_RESOURCE_VIDEO)) |
870 | mutex_unlock(&dev->lock); | 1070 | return POLLERR; |
871 | 1071 | return videobuf_poll_stream(filp, &fh->vb_vidq, wait); | |
872 | if (unlikely(rc < 0)) | 1072 | } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
873 | return POLLERR; | 1073 | if (!res_get(fh, AU0828_RESOURCE_VBI)) |
874 | 1074 | return POLLERR; | |
875 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type) | 1075 | return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); |
1076 | } else { | ||
876 | return POLLERR; | 1077 | return POLLERR; |
877 | 1078 | } | |
878 | return videobuf_poll_stream(filp, &fh->vb_vidq, wait); | ||
879 | } | 1079 | } |
880 | 1080 | ||
881 | static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | 1081 | static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) |
@@ -888,14 +1088,10 @@ static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | |||
888 | if (rc < 0) | 1088 | if (rc < 0) |
889 | return rc; | 1089 | return rc; |
890 | 1090 | ||
891 | mutex_lock(&dev->lock); | 1091 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
892 | rc = res_get(fh); | 1092 | rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); |
893 | mutex_unlock(&dev->lock); | 1093 | else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) |
894 | 1094 | rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma); | |
895 | if (unlikely(rc < 0)) | ||
896 | return rc; | ||
897 | |||
898 | rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); | ||
899 | 1095 | ||
900 | return rc; | 1096 | return rc; |
901 | } | 1097 | } |
@@ -911,14 +1107,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, | |||
911 | maxwidth = 720; | 1107 | maxwidth = 720; |
912 | maxheight = 480; | 1108 | maxheight = 480; |
913 | 1109 | ||
914 | #ifdef VBI_IS_WORKING | ||
915 | if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
916 | dprintk(1, "VBI format set: to be supported!\n"); | ||
917 | return 0; | ||
918 | } | ||
919 | if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE) | ||
920 | return 0; | ||
921 | #endif | ||
922 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1110 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
923 | return -EINVAL; | 1111 | return -EINVAL; |
924 | 1112 | ||
@@ -999,9 +1187,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
999 | 1187 | ||
1000 | /*set the device capabilities */ | 1188 | /*set the device capabilities */ |
1001 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | 1189 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | |
1002 | #ifdef VBI_IS_WORKING | ||
1003 | V4L2_CAP_VBI_CAPTURE | | 1190 | V4L2_CAP_VBI_CAPTURE | |
1004 | #endif | ||
1005 | V4L2_CAP_AUDIO | | 1191 | V4L2_CAP_AUDIO | |
1006 | V4L2_CAP_READWRITE | | 1192 | V4L2_CAP_READWRITE | |
1007 | V4L2_CAP_STREAMING | | 1193 | V4L2_CAP_STREAMING | |
@@ -1056,20 +1242,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
1056 | struct au0828_dev *dev = fh->dev; | 1242 | struct au0828_dev *dev = fh->dev; |
1057 | int rc; | 1243 | int rc; |
1058 | 1244 | ||
1245 | rc = check_dev(dev); | ||
1246 | if (rc < 0) | ||
1247 | return rc; | ||
1248 | |||
1249 | mutex_lock(&dev->lock); | ||
1250 | |||
1059 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 1251 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
1060 | printk(KERN_INFO "%s queue busy\n", __func__); | 1252 | printk(KERN_INFO "%s queue busy\n", __func__); |
1061 | rc = -EBUSY; | 1253 | rc = -EBUSY; |
1062 | goto out; | 1254 | goto out; |
1063 | } | 1255 | } |
1064 | 1256 | ||
1065 | if (dev->stream_on && !fh->stream_on) { | 1257 | rc = au0828_set_format(dev, VIDIOC_S_FMT, f); |
1066 | printk(KERN_INFO "%s device in use by another fh\n", __func__); | ||
1067 | rc = -EBUSY; | ||
1068 | goto out; | ||
1069 | } | ||
1070 | |||
1071 | return au0828_set_format(dev, VIDIOC_S_FMT, f); | ||
1072 | out: | 1258 | out: |
1259 | mutex_unlock(&dev->lock); | ||
1073 | return rc; | 1260 | return rc; |
1074 | } | 1261 | } |
1075 | 1262 | ||
@@ -1300,6 +1487,29 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
1300 | return 0; | 1487 | return 0; |
1301 | } | 1488 | } |
1302 | 1489 | ||
1490 | |||
1491 | /* RAW VBI ioctls */ | ||
1492 | |||
1493 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | ||
1494 | struct v4l2_format *format) | ||
1495 | { | ||
1496 | struct au0828_fh *fh = priv; | ||
1497 | struct au0828_dev *dev = fh->dev; | ||
1498 | |||
1499 | format->fmt.vbi.samples_per_line = dev->vbi_width; | ||
1500 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | ||
1501 | format->fmt.vbi.offset = 0; | ||
1502 | format->fmt.vbi.flags = 0; | ||
1503 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; | ||
1504 | |||
1505 | format->fmt.vbi.count[0] = dev->vbi_height; | ||
1506 | format->fmt.vbi.count[1] = dev->vbi_height; | ||
1507 | format->fmt.vbi.start[0] = 21; | ||
1508 | format->fmt.vbi.start[1] = 284; | ||
1509 | |||
1510 | return 0; | ||
1511 | } | ||
1512 | |||
1303 | static int vidioc_g_chip_ident(struct file *file, void *priv, | 1513 | static int vidioc_g_chip_ident(struct file *file, void *priv, |
1304 | struct v4l2_dbg_chip_ident *chip) | 1514 | struct v4l2_dbg_chip_ident *chip) |
1305 | { | 1515 | { |
@@ -1345,25 +1555,32 @@ static int vidioc_cropcap(struct file *file, void *priv, | |||
1345 | static int vidioc_streamon(struct file *file, void *priv, | 1555 | static int vidioc_streamon(struct file *file, void *priv, |
1346 | enum v4l2_buf_type type) | 1556 | enum v4l2_buf_type type) |
1347 | { | 1557 | { |
1348 | struct au0828_fh *fh = priv; | 1558 | struct au0828_fh *fh = priv; |
1349 | struct au0828_dev *dev = fh->dev; | 1559 | struct au0828_dev *dev = fh->dev; |
1350 | int rc; | 1560 | int rc = -EINVAL; |
1351 | 1561 | ||
1352 | rc = check_dev(dev); | 1562 | rc = check_dev(dev); |
1353 | if (rc < 0) | 1563 | if (rc < 0) |
1354 | return rc; | 1564 | return rc; |
1355 | 1565 | ||
1566 | if (unlikely(type != fh->type)) | ||
1567 | return -EINVAL; | ||
1568 | |||
1569 | dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n", | ||
1570 | fh, type, fh->resources, dev->resources); | ||
1571 | |||
1572 | if (unlikely(!res_get(fh, get_ressource(fh)))) | ||
1573 | return -EBUSY; | ||
1574 | |||
1356 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1575 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1357 | au0828_analog_stream_enable(dev); | 1576 | au0828_analog_stream_enable(dev); |
1358 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); | 1577 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); |
1359 | } | 1578 | } |
1360 | 1579 | ||
1361 | mutex_lock(&dev->lock); | 1580 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1362 | rc = res_get(fh); | ||
1363 | |||
1364 | if (likely(rc >= 0)) | ||
1365 | rc = videobuf_streamon(&fh->vb_vidq); | 1581 | rc = videobuf_streamon(&fh->vb_vidq); |
1366 | mutex_unlock(&dev->lock); | 1582 | else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) |
1583 | rc = videobuf_streamon(&fh->vb_vbiq); | ||
1367 | 1584 | ||
1368 | return rc; | 1585 | return rc; |
1369 | } | 1586 | } |
@@ -1371,38 +1588,42 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
1371 | static int vidioc_streamoff(struct file *file, void *priv, | 1588 | static int vidioc_streamoff(struct file *file, void *priv, |
1372 | enum v4l2_buf_type type) | 1589 | enum v4l2_buf_type type) |
1373 | { | 1590 | { |
1374 | struct au0828_fh *fh = priv; | 1591 | struct au0828_fh *fh = priv; |
1375 | struct au0828_dev *dev = fh->dev; | 1592 | struct au0828_dev *dev = fh->dev; |
1376 | int i; | 1593 | int rc; |
1377 | int ret; | 1594 | int i; |
1378 | int rc; | ||
1379 | 1595 | ||
1380 | rc = check_dev(dev); | 1596 | rc = check_dev(dev); |
1381 | if (rc < 0) | 1597 | if (rc < 0) |
1382 | return rc; | 1598 | return rc; |
1383 | 1599 | ||
1384 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1600 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && |
1601 | fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) | ||
1385 | return -EINVAL; | 1602 | return -EINVAL; |
1386 | if (type != fh->type) | 1603 | if (type != fh->type) |
1387 | return -EINVAL; | 1604 | return -EINVAL; |
1388 | 1605 | ||
1389 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1606 | dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n", |
1607 | fh, type, fh->resources, dev->resources); | ||
1608 | |||
1609 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1390 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); | 1610 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); |
1391 | ret = au0828_stream_interrupt(dev); | 1611 | rc = au0828_stream_interrupt(dev); |
1392 | if (ret != 0) | 1612 | if (rc != 0) |
1393 | return ret; | 1613 | return rc; |
1394 | } | ||
1395 | 1614 | ||
1396 | for (i = 0; i < AU0828_MAX_INPUT; i++) { | 1615 | for (i = 0; i < AU0828_MAX_INPUT; i++) { |
1397 | if (AUVI_INPUT(i).audio_setup == NULL) | 1616 | if (AUVI_INPUT(i).audio_setup == NULL) |
1398 | continue; | 1617 | continue; |
1399 | (AUVI_INPUT(i).audio_setup)(dev, 0); | 1618 | (AUVI_INPUT(i).audio_setup)(dev, 0); |
1400 | } | 1619 | } |
1401 | 1620 | ||
1402 | mutex_lock(&dev->lock); | 1621 | videobuf_streamoff(&fh->vb_vidq); |
1403 | videobuf_streamoff(&fh->vb_vidq); | 1622 | res_free(fh, AU0828_RESOURCE_VIDEO); |
1404 | res_free(fh); | 1623 | } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
1405 | mutex_unlock(&dev->lock); | 1624 | videobuf_streamoff(&fh->vb_vbiq); |
1625 | res_free(fh, AU0828_RESOURCE_VBI); | ||
1626 | } | ||
1406 | 1627 | ||
1407 | return 0; | 1628 | return 0; |
1408 | } | 1629 | } |
@@ -1527,19 +1748,11 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1527 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1748 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
1528 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 1749 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, |
1529 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 1750 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1530 | #ifdef VBI_IS_WORKING | ||
1531 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, | 1751 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, |
1532 | .vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, | 1752 | .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, |
1533 | .vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap, | ||
1534 | #endif | ||
1535 | .vidioc_g_audio = vidioc_g_audio, | 1753 | .vidioc_g_audio = vidioc_g_audio, |
1536 | .vidioc_s_audio = vidioc_s_audio, | 1754 | .vidioc_s_audio = vidioc_s_audio, |
1537 | .vidioc_cropcap = vidioc_cropcap, | 1755 | .vidioc_cropcap = vidioc_cropcap, |
1538 | #ifdef VBI_IS_WORKING | ||
1539 | .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap, | ||
1540 | .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, | ||
1541 | .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap, | ||
1542 | #endif | ||
1543 | .vidioc_reqbufs = vidioc_reqbufs, | 1756 | .vidioc_reqbufs = vidioc_reqbufs, |
1544 | .vidioc_querybuf = vidioc_querybuf, | 1757 | .vidioc_querybuf = vidioc_querybuf, |
1545 | .vidioc_qbuf = vidioc_qbuf, | 1758 | .vidioc_qbuf = vidioc_qbuf, |
@@ -1621,8 +1834,11 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1621 | spin_lock_init(&dev->slock); | 1834 | spin_lock_init(&dev->slock); |
1622 | mutex_init(&dev->lock); | 1835 | mutex_init(&dev->lock); |
1623 | 1836 | ||
1837 | /* init video dma queues */ | ||
1624 | INIT_LIST_HEAD(&dev->vidq.active); | 1838 | INIT_LIST_HEAD(&dev->vidq.active); |
1625 | INIT_LIST_HEAD(&dev->vidq.queued); | 1839 | INIT_LIST_HEAD(&dev->vidq.queued); |
1840 | INIT_LIST_HEAD(&dev->vbiq.active); | ||
1841 | INIT_LIST_HEAD(&dev->vbiq.queued); | ||
1626 | 1842 | ||
1627 | dev->width = NTSC_STD_W; | 1843 | dev->width = NTSC_STD_W; |
1628 | dev->height = NTSC_STD_H; | 1844 | dev->height = NTSC_STD_H; |
@@ -1638,26 +1854,23 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1638 | return -ENOMEM; | 1854 | return -ENOMEM; |
1639 | } | 1855 | } |
1640 | 1856 | ||
1641 | #ifdef VBI_IS_WORKING | 1857 | /* allocate the VBI struct */ |
1642 | dev->vbi_dev = video_device_alloc(); | 1858 | dev->vbi_dev = video_device_alloc(); |
1643 | if (NULL == dev->vbi_dev) { | 1859 | if (NULL == dev->vbi_dev) { |
1644 | dprintk(1, "Can't allocate vbi_device.\n"); | 1860 | dprintk(1, "Can't allocate vbi_device.\n"); |
1645 | kfree(dev->vdev); | 1861 | kfree(dev->vdev); |
1646 | return -ENOMEM; | 1862 | return -ENOMEM; |
1647 | } | 1863 | } |
1648 | #endif | ||
1649 | 1864 | ||
1650 | /* Fill the video capture device struct */ | 1865 | /* Fill the video capture device struct */ |
1651 | *dev->vdev = au0828_video_template; | 1866 | *dev->vdev = au0828_video_template; |
1652 | dev->vdev->parent = &dev->usbdev->dev; | 1867 | dev->vdev->parent = &dev->usbdev->dev; |
1653 | strcpy(dev->vdev->name, "au0828a video"); | 1868 | strcpy(dev->vdev->name, "au0828a video"); |
1654 | 1869 | ||
1655 | #ifdef VBI_IS_WORKING | ||
1656 | /* Setup the VBI device */ | 1870 | /* Setup the VBI device */ |
1657 | *dev->vbi_dev = au0828_video_template; | 1871 | *dev->vbi_dev = au0828_video_template; |
1658 | dev->vbi_dev->parent = &dev->usbdev->dev; | 1872 | dev->vbi_dev->parent = &dev->usbdev->dev; |
1659 | strcpy(dev->vbi_dev->name, "au0828a vbi"); | 1873 | strcpy(dev->vbi_dev->name, "au0828a vbi"); |
1660 | #endif | ||
1661 | 1874 | ||
1662 | /* Register the v4l2 device */ | 1875 | /* Register the v4l2 device */ |
1663 | video_set_drvdata(dev->vdev, dev); | 1876 | video_set_drvdata(dev->vdev, dev); |
@@ -1669,7 +1882,6 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1669 | return -ENODEV; | 1882 | return -ENODEV; |
1670 | } | 1883 | } |
1671 | 1884 | ||
1672 | #ifdef VBI_IS_WORKING | ||
1673 | /* Register the vbi device */ | 1885 | /* Register the vbi device */ |
1674 | video_set_drvdata(dev->vbi_dev, dev); | 1886 | video_set_drvdata(dev->vbi_dev, dev); |
1675 | retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); | 1887 | retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); |
@@ -1680,7 +1892,6 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1680 | video_device_release(dev->vdev); | 1892 | video_device_release(dev->vdev); |
1681 | return -ENODEV; | 1893 | return -ENODEV; |
1682 | } | 1894 | } |
1683 | #endif | ||
1684 | 1895 | ||
1685 | dprintk(1, "%s completed!\n", __func__); | 1896 | dprintk(1, "%s completed!\n", __func__); |
1686 | 1897 | ||