diff options
Diffstat (limited to 'drivers/media/video/vivi.c')
-rw-r--r-- | drivers/media/video/vivi.c | 664 |
1 files changed, 299 insertions, 365 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 779db26771c0..41d23c8acbd8 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -48,34 +48,15 @@ | |||
48 | 48 | ||
49 | #include "font.h" | 49 | #include "font.h" |
50 | 50 | ||
51 | #ifndef kzalloc | ||
52 | #define kzalloc(size, flags) \ | ||
53 | ({ \ | ||
54 | void *__ret = kmalloc(size, flags); \ | ||
55 | if (__ret) \ | ||
56 | memset(__ret, 0, size); \ | ||
57 | __ret; \ | ||
58 | }) | ||
59 | #endif | ||
60 | |||
61 | MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); | ||
62 | MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); | ||
63 | MODULE_LICENSE("Dual BSD/GPL"); | ||
64 | |||
65 | #define VIVI_MAJOR_VERSION 0 | 51 | #define VIVI_MAJOR_VERSION 0 |
66 | #define VIVI_MINOR_VERSION 4 | 52 | #define VIVI_MINOR_VERSION 4 |
67 | #define VIVI_RELEASE 0 | 53 | #define VIVI_RELEASE 0 |
68 | #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) | 54 | #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) |
69 | 55 | ||
70 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ | 56 | /* Declare static vars that will be used as parameters */ |
71 | module_param(video_nr, int, 0); | 57 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ |
72 | 58 | static struct video_device vivi; /* Video device */ | |
73 | static int debug = 0; | 59 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ |
74 | module_param(debug, int, 0); | ||
75 | |||
76 | static unsigned int vid_limit = 16; | ||
77 | module_param(vid_limit,int,0644); | ||
78 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
79 | 60 | ||
80 | /* supported controls */ | 61 | /* supported controls */ |
81 | static struct v4l2_queryctrl vivi_qctrl[] = { | 62 | static struct v4l2_queryctrl vivi_qctrl[] = { |
@@ -129,10 +110,10 @@ static struct v4l2_queryctrl vivi_qctrl[] = { | |||
129 | 110 | ||
130 | static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; | 111 | static int qctl_regs[ARRAY_SIZE(vivi_qctrl)]; |
131 | 112 | ||
132 | #define dprintk(level,fmt, arg...) \ | 113 | #define dprintk(level,fmt, arg...) \ |
133 | do { \ | 114 | do { \ |
134 | if (debug >= (level)) \ | 115 | if (vivi.debug >= (level)) \ |
135 | printk(KERN_DEBUG "vivi: " fmt , ## arg); \ | 116 | printk(KERN_DEBUG "vivi: " fmt , ## arg); \ |
136 | } while (0) | 117 | } while (0) |
137 | 118 | ||
138 | /* ------------------------------------------------------------------ | 119 | /* ------------------------------------------------------------------ |
@@ -190,7 +171,7 @@ struct vivi_dev { | |||
190 | 171 | ||
191 | /* various device info */ | 172 | /* various device info */ |
192 | unsigned int resources; | 173 | unsigned int resources; |
193 | struct video_device video_dev; | 174 | struct video_device vfd; |
194 | 175 | ||
195 | struct vivi_dmaqueue vidq; | 176 | struct vivi_dmaqueue vidq; |
196 | 177 | ||
@@ -248,7 +229,8 @@ static u8 bars[8][3] = { | |||
248 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 | 229 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 |
249 | #define TSTAMP_MIN_X 64 | 230 | #define TSTAMP_MIN_X 64 |
250 | 231 | ||
251 | void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb) | 232 | static void prep_to_addr(struct sg_to_addr to_addr[], |
233 | struct videobuf_buffer *vb) | ||
252 | { | 234 | { |
253 | int i, pos=0; | 235 | int i, pos=0; |
254 | 236 | ||
@@ -259,7 +241,7 @@ void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb) | |||
259 | } | 241 | } |
260 | } | 242 | } |
261 | 243 | ||
262 | inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) | 244 | static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) |
263 | { | 245 | { |
264 | int p1=0,p2=pages-1,p3=pages/2; | 246 | int p1=0,p2=pages-1,p3=pages/2; |
265 | 247 | ||
@@ -280,8 +262,8 @@ inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) | |||
280 | return (p1); | 262 | return (p1); |
281 | } | 263 | } |
282 | 264 | ||
283 | void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | 265 | static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, |
284 | int hmax, int line, char *timestr) | 266 | int hmax, int line, char *timestr) |
285 | { | 267 | { |
286 | int w,i,j,pos=inipos,pgpos,oldpg,y; | 268 | int w,i,j,pos=inipos,pgpos,oldpg,y; |
287 | char *p,*s,*basep; | 269 | char *p,*s,*basep; |
@@ -491,7 +473,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue *dma_q) | |||
491 | dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); | 473 | dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc); |
492 | } | 474 | } |
493 | 475 | ||
494 | void vivi_sleep(struct vivi_dmaqueue *dma_q) | 476 | static void vivi_sleep(struct vivi_dmaqueue *dma_q) |
495 | { | 477 | { |
496 | int timeout; | 478 | int timeout; |
497 | DECLARE_WAITQUEUE(wait, current); | 479 | DECLARE_WAITQUEUE(wait, current); |
@@ -526,7 +508,7 @@ void vivi_sleep(struct vivi_dmaqueue *dma_q) | |||
526 | try_to_freeze(); | 508 | try_to_freeze(); |
527 | } | 509 | } |
528 | 510 | ||
529 | int vivi_thread(void *data) | 511 | static int vivi_thread(void *data) |
530 | { | 512 | { |
531 | struct vivi_dmaqueue *dma_q=data; | 513 | struct vivi_dmaqueue *dma_q=data; |
532 | 514 | ||
@@ -542,7 +524,7 @@ int vivi_thread(void *data) | |||
542 | return 0; | 524 | return 0; |
543 | } | 525 | } |
544 | 526 | ||
545 | int vivi_start_thread(struct vivi_dmaqueue *dma_q) | 527 | static int vivi_start_thread(struct vivi_dmaqueue *dma_q) |
546 | { | 528 | { |
547 | dma_q->frame=0; | 529 | dma_q->frame=0; |
548 | dma_q->ini_jiffies=jiffies; | 530 | dma_q->ini_jiffies=jiffies; |
@@ -560,7 +542,7 @@ int vivi_start_thread(struct vivi_dmaqueue *dma_q) | |||
560 | return 0; | 542 | return 0; |
561 | } | 543 | } |
562 | 544 | ||
563 | void vivi_stop_thread(struct vivi_dmaqueue *dma_q) | 545 | static void vivi_stop_thread(struct vivi_dmaqueue *dma_q) |
564 | { | 546 | { |
565 | dprintk(1,"%s\n",__FUNCTION__); | 547 | dprintk(1,"%s\n",__FUNCTION__); |
566 | /* shutdown control thread */ | 548 | /* shutdown control thread */ |
@@ -666,8 +648,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) | |||
666 | return 0; | 648 | return 0; |
667 | } | 649 | } |
668 | 650 | ||
669 | void | 651 | static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) |
670 | free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) | ||
671 | { | 652 | { |
672 | dprintk(1,"%s\n",__FUNCTION__); | 653 | dprintk(1,"%s\n",__FUNCTION__); |
673 | 654 | ||
@@ -791,8 +772,8 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb | |||
791 | free_buffer(vq,buf); | 772 | free_buffer(vq,buf); |
792 | } | 773 | } |
793 | 774 | ||
794 | int vivi_map_sg (void *dev, struct scatterlist *sg, int nents, | 775 | static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents, |
795 | int direction) | 776 | int direction) |
796 | { | 777 | { |
797 | int i; | 778 | int i; |
798 | 779 | ||
@@ -808,15 +789,15 @@ int vivi_map_sg (void *dev, struct scatterlist *sg, int nents, | |||
808 | return nents; | 789 | return nents; |
809 | } | 790 | } |
810 | 791 | ||
811 | int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, | 792 | static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, |
812 | int direction) | 793 | int direction) |
813 | { | 794 | { |
814 | dprintk(1,"%s\n",__FUNCTION__); | 795 | dprintk(1,"%s\n",__FUNCTION__); |
815 | return 0; | 796 | return 0; |
816 | } | 797 | } |
817 | 798 | ||
818 | int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages, | 799 | static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages, |
819 | int direction) | 800 | int direction) |
820 | { | 801 | { |
821 | // dprintk(1,"%s\n",__FUNCTION__); | 802 | // dprintk(1,"%s\n",__FUNCTION__); |
822 | 803 | ||
@@ -840,7 +821,80 @@ static struct videobuf_queue_ops vivi_video_qops = { | |||
840 | IOCTL handling | 821 | IOCTL handling |
841 | ------------------------------------------------------------------*/ | 822 | ------------------------------------------------------------------*/ |
842 | 823 | ||
843 | static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | 824 | |
825 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | ||
826 | { | ||
827 | /* is it free? */ | ||
828 | down(&dev->lock); | ||
829 | if (dev->resources) { | ||
830 | /* no, someone else uses it */ | ||
831 | up(&dev->lock); | ||
832 | return 0; | ||
833 | } | ||
834 | /* it's free, grab it */ | ||
835 | dev->resources =1; | ||
836 | dprintk(1,"res: get\n"); | ||
837 | up(&dev->lock); | ||
838 | return 1; | ||
839 | } | ||
840 | |||
841 | static int res_locked(struct vivi_dev *dev) | ||
842 | { | ||
843 | return (dev->resources); | ||
844 | } | ||
845 | |||
846 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | ||
847 | { | ||
848 | down(&dev->lock); | ||
849 | dev->resources = 0; | ||
850 | dprintk(1,"res: put\n"); | ||
851 | up(&dev->lock); | ||
852 | } | ||
853 | |||
854 | /* ------------------------------------------------------------------ | ||
855 | IOCTL vidioc handling | ||
856 | ------------------------------------------------------------------*/ | ||
857 | static int vidioc_querycap (struct file *file, void *priv, | ||
858 | struct v4l2_capability *cap) | ||
859 | { | ||
860 | strcpy(cap->driver, "vivi"); | ||
861 | strcpy(cap->card, "vivi"); | ||
862 | cap->version = VIVI_VERSION; | ||
863 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | ||
864 | V4L2_CAP_STREAMING | | ||
865 | V4L2_CAP_READWRITE; | ||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | static int vidioc_enum_fmt_cap (struct file *file, void *priv, | ||
870 | struct v4l2_fmtdesc *f) | ||
871 | { | ||
872 | if (f->index > 0) | ||
873 | return -EINVAL; | ||
874 | |||
875 | strlcpy(f->description,format.name,sizeof(f->description)); | ||
876 | f->pixelformat = format.fourcc; | ||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | static int vidioc_g_fmt_cap (struct file *file, void *priv, | ||
881 | struct v4l2_format *f) | ||
882 | { | ||
883 | struct vivi_fh *fh=priv; | ||
884 | |||
885 | f->fmt.pix.width = fh->width; | ||
886 | f->fmt.pix.height = fh->height; | ||
887 | f->fmt.pix.field = fh->vb_vidq.field; | ||
888 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
889 | f->fmt.pix.bytesperline = | ||
890 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
891 | f->fmt.pix.sizeimage = | ||
892 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
893 | |||
894 | return (0); | ||
895 | } | ||
896 | |||
897 | static int vidioc_try_fmt_cap (struct file *file, void *priv, | ||
844 | struct v4l2_format *f) | 898 | struct v4l2_format *f) |
845 | { | 899 | { |
846 | struct vivi_fmt *fmt; | 900 | struct vivi_fmt *fmt; |
@@ -848,7 +902,8 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | |||
848 | unsigned int maxw, maxh; | 902 | unsigned int maxw, maxh; |
849 | 903 | ||
850 | if (format.fourcc != f->fmt.pix.pixelformat) { | 904 | if (format.fourcc != f->fmt.pix.pixelformat) { |
851 | dprintk(1,"Fourcc format invalid.\n"); | 905 | dprintk(1,"Fourcc format (0x%08x) invalid. Driver accepts " |
906 | "only 0x%08x\n",f->fmt.pix.pixelformat,format.fourcc); | ||
852 | return -EINVAL; | 907 | return -EINVAL; |
853 | } | 908 | } |
854 | fmt=&format; | 909 | fmt=&format; |
@@ -884,356 +939,196 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh, | |||
884 | return 0; | 939 | return 0; |
885 | } | 940 | } |
886 | 941 | ||
887 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | 942 | /*FIXME: This seems to be generic enough to be at videodev2 */ |
943 | static int vidioc_s_fmt_cap (struct file *file, void *priv, | ||
944 | struct v4l2_format *f) | ||
888 | { | 945 | { |
889 | /* is it free? */ | 946 | struct vivi_fh *fh=priv; |
890 | down(&dev->lock); | 947 | int ret = vidioc_try_fmt_cap(file,fh,f); |
891 | if (dev->resources) { | 948 | if (ret < 0) |
892 | /* no, someone else uses it */ | 949 | return (ret); |
893 | up(&dev->lock); | 950 | |
894 | return 0; | 951 | fh->fmt = &format; |
895 | } | 952 | fh->width = f->fmt.pix.width; |
896 | /* it's free, grab it */ | 953 | fh->height = f->fmt.pix.height; |
897 | dev->resources =1; | 954 | fh->vb_vidq.field = f->fmt.pix.field; |
898 | dprintk(1,"res: get\n"); | 955 | fh->type = f->type; |
899 | up(&dev->lock); | 956 | |
900 | return 1; | 957 | return (0); |
901 | } | 958 | } |
902 | 959 | ||
903 | static inline int res_locked(struct vivi_dev *dev) | 960 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) |
904 | { | 961 | { |
905 | return (dev->resources); | 962 | struct vivi_fh *fh=priv; |
906 | } | ||
907 | 963 | ||
908 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | 964 | return (videobuf_reqbufs(&fh->vb_vidq, p)); |
909 | { | ||
910 | down(&dev->lock); | ||
911 | dev->resources = 0; | ||
912 | dprintk(1,"res: put\n"); | ||
913 | up(&dev->lock); | ||
914 | } | 965 | } |
915 | 966 | ||
916 | static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) | 967 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) |
917 | { | 968 | { |
918 | struct vivi_fh *fh = file->private_data; | 969 | struct vivi_fh *fh=priv; |
919 | struct vivi_dev *dev = fh->dev; | ||
920 | int ret=0; | ||
921 | 970 | ||
922 | if (debug) { | 971 | return (videobuf_querybuf(&fh->vb_vidq, p)); |
923 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 972 | } |
924 | v4l_printk_ioctl_arg("vivi(w)",cmd, arg); | ||
925 | else if (!_IOC_DIR(cmd) & _IOC_READ) { | ||
926 | v4l_print_ioctl("vivi", cmd); | ||
927 | } | ||
928 | } | ||
929 | 973 | ||
930 | switch(cmd) { | 974 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
931 | /* --- capabilities ------------------------------------------ */ | 975 | { |
932 | case VIDIOC_QUERYCAP: | 976 | struct vivi_fh *fh=priv; |
933 | { | ||
934 | struct v4l2_capability *cap = (struct v4l2_capability*)arg; | ||
935 | |||
936 | memset(cap, 0, sizeof(*cap)); | ||
937 | |||
938 | strcpy(cap->driver, "vivi"); | ||
939 | strcpy(cap->card, "vivi"); | ||
940 | cap->version = VIVI_VERSION; | ||
941 | cap->capabilities = | ||
942 | V4L2_CAP_VIDEO_CAPTURE | | ||
943 | V4L2_CAP_STREAMING | | ||
944 | V4L2_CAP_READWRITE; | ||
945 | break; | ||
946 | } | ||
947 | /* --- capture ioctls ---------------------------------------- */ | ||
948 | case VIDIOC_ENUM_FMT: | ||
949 | { | ||
950 | struct v4l2_fmtdesc *f = arg; | ||
951 | enum v4l2_buf_type type; | ||
952 | unsigned int index; | ||
953 | 977 | ||
954 | index = f->index; | 978 | return (videobuf_qbuf(&fh->vb_vidq, p)); |
955 | type = f->type; | 979 | } |
956 | 980 | ||
957 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 981 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) |
958 | ret=-EINVAL; | 982 | { |
959 | break; | 983 | struct vivi_fh *fh=priv; |
960 | } | ||
961 | 984 | ||
962 | switch (type) { | 985 | return (videobuf_dqbuf(&fh->vb_vidq, p, |
963 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 986 | file->f_flags & O_NONBLOCK)); |
964 | if (index > 0){ | 987 | } |
965 | ret=-EINVAL; | ||
966 | break; | ||
967 | } | ||
968 | memset(f,0,sizeof(*f)); | ||
969 | 988 | ||
970 | f->index = index; | 989 | #ifdef HAVE_V4L1 |
971 | f->type = type; | 990 | static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) |
972 | strlcpy(f->description,format.name,sizeof(f->description)); | 991 | { |
973 | f->pixelformat = format.fourcc; | 992 | struct vivi_fh *fh=priv; |
974 | break; | 993 | struct videobuf_queue *q=&fh->vb_vidq; |
975 | default: | 994 | struct v4l2_requestbuffers req; |
976 | ret=-EINVAL; | 995 | unsigned int i, ret; |
977 | } | 996 | |
978 | break; | 997 | req.type = q->type; |
998 | req.count = 8; | ||
999 | req.memory = V4L2_MEMORY_MMAP; | ||
1000 | ret = videobuf_reqbufs(q,&req); | ||
1001 | if (ret < 0) | ||
1002 | return (ret); | ||
1003 | |||
1004 | mbuf->frames = req.count; | ||
1005 | mbuf->size = 0; | ||
1006 | for (i = 0; i < mbuf->frames; i++) { | ||
1007 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1008 | mbuf->size += q->bufs[i]->bsize; | ||
979 | } | 1009 | } |
980 | case VIDIOC_G_FMT: | 1010 | return (0); |
981 | { | 1011 | } |
982 | struct v4l2_format *f = (struct v4l2_format *)arg; | 1012 | #endif |
983 | 1013 | ||
984 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1014 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
985 | ret=-EINVAL; | 1015 | { |
986 | break; | 1016 | struct vivi_fh *fh=priv; |
987 | } | 1017 | struct vivi_dev *dev = fh->dev; |
988 | 1018 | ||
989 | memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); | 1019 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
990 | f->fmt.pix.width = fh->width; | 1020 | return -EINVAL; |
991 | f->fmt.pix.height = fh->height; | 1021 | if (i != fh->type) |
992 | f->fmt.pix.field = fh->vb_vidq.field; | 1022 | return -EINVAL; |
993 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
994 | f->fmt.pix.bytesperline = | ||
995 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
996 | f->fmt.pix.sizeimage = | ||
997 | f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
998 | break; | ||
999 | } | ||
1000 | case VIDIOC_S_FMT: | ||
1001 | { | ||
1002 | struct v4l2_format *f = arg; | ||
1003 | 1023 | ||
1004 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1024 | if (!res_get(dev,fh)) |
1005 | dprintk(1,"Only capture supported.\n"); | 1025 | return -EBUSY; |
1006 | ret=-EINVAL; | 1026 | return (videobuf_streamon(&fh->vb_vidq)); |
1007 | break; | 1027 | } |
1008 | } | ||
1009 | 1028 | ||
1010 | ret = vivi_try_fmt(dev,fh,f); | 1029 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
1011 | if (ret < 0) | 1030 | { |
1012 | break; | 1031 | struct vivi_fh *fh=priv; |
1032 | struct vivi_dev *dev = fh->dev; | ||
1013 | 1033 | ||
1014 | fh->fmt = &format; | 1034 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1015 | fh->width = f->fmt.pix.width; | 1035 | return -EINVAL; |
1016 | fh->height = f->fmt.pix.height; | 1036 | if (i != fh->type) |
1017 | fh->vb_vidq.field = f->fmt.pix.field; | 1037 | return -EINVAL; |
1018 | fh->type = f->type; | ||
1019 | 1038 | ||
1020 | break; | 1039 | videobuf_streamoff(&fh->vb_vidq); |
1021 | } | 1040 | res_free(dev,fh); |
1022 | case VIDIOC_TRY_FMT: | ||
1023 | { | ||
1024 | struct v4l2_format *f = arg; | ||
1025 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1026 | ret=-EINVAL; | ||
1027 | break; | ||
1028 | } | ||
1029 | 1041 | ||
1030 | ret=vivi_try_fmt(dev,fh,f); | 1042 | return (0); |
1031 | break; | 1043 | } |
1032 | } | 1044 | |
1033 | case VIDIOC_REQBUFS: | 1045 | static struct v4l2_tvnorm tvnorms[] = { |
1034 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1035 | ret=-EINVAL; | ||
1036 | break; | ||
1037 | } | ||
1038 | ret=videobuf_reqbufs(&fh->vb_vidq, arg); | ||
1039 | break; | ||
1040 | case VIDIOC_QUERYBUF: | ||
1041 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1042 | ret=-EINVAL; | ||
1043 | break; | ||
1044 | } | ||
1045 | ret=videobuf_querybuf(&fh->vb_vidq, arg); | ||
1046 | break; | ||
1047 | case VIDIOC_QBUF: | ||
1048 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1049 | ret=-EINVAL; | ||
1050 | break; | ||
1051 | } | ||
1052 | ret=videobuf_qbuf(&fh->vb_vidq, arg); | ||
1053 | break; | ||
1054 | case VIDIOC_DQBUF: | ||
1055 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1056 | ret=-EINVAL; | ||
1057 | break; | ||
1058 | } | ||
1059 | ret=videobuf_dqbuf(&fh->vb_vidq, arg, | ||
1060 | file->f_flags & O_NONBLOCK); | ||
1061 | break; | ||
1062 | #ifdef HAVE_V4L1 | ||
1063 | /* --- streaming capture ------------------------------------- */ | ||
1064 | case VIDIOCGMBUF: | ||
1065 | { | ||
1066 | struct video_mbuf *mbuf = arg; | ||
1067 | struct videobuf_queue *q=&fh->vb_vidq; | ||
1068 | struct v4l2_requestbuffers req; | ||
1069 | unsigned int i; | ||
1070 | |||
1071 | memset(&req,0,sizeof(req)); | ||
1072 | req.type = q->type; | ||
1073 | req.count = 8; | ||
1074 | req.memory = V4L2_MEMORY_MMAP; | ||
1075 | ret = videobuf_reqbufs(q,&req); | ||
1076 | if (ret < 0) | ||
1077 | break; | ||
1078 | memset(mbuf,0,sizeof(*mbuf)); | ||
1079 | mbuf->frames = req.count; | ||
1080 | mbuf->size = 0; | ||
1081 | for (i = 0; i < mbuf->frames; i++) { | ||
1082 | mbuf->offsets[i] = q->bufs[i]->boff; | ||
1083 | mbuf->size += q->bufs[i]->bsize; | ||
1084 | } | ||
1085 | break; | ||
1086 | } | ||
1087 | #endif | ||
1088 | case VIDIOC_STREAMON: | ||
1089 | { | ||
1090 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1091 | return -EINVAL; | ||
1092 | if (!res_get(dev,fh)) | ||
1093 | return -EBUSY; | ||
1094 | ret=videobuf_streamon(&fh->vb_vidq); | ||
1095 | break; | ||
1096 | } | ||
1097 | case VIDIOC_STREAMOFF: | ||
1098 | { | 1046 | { |
1099 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1047 | .name = "NTSC-M", |
1100 | ret=-EINVAL; | 1048 | .id = V4L2_STD_NTSC_M, |
1101 | break; | ||
1102 | } | ||
1103 | ret = videobuf_streamoff(&fh->vb_vidq); | ||
1104 | if (ret < 0) | ||
1105 | break; | ||
1106 | res_free(dev,fh); | ||
1107 | break; | ||
1108 | } | 1049 | } |
1109 | /* ---------- tv norms ---------- */ | 1050 | }; |
1110 | case VIDIOC_ENUMSTD: | ||
1111 | { | ||
1112 | struct v4l2_standard *e = arg; | ||
1113 | 1051 | ||
1114 | if (e->index>0) { | 1052 | static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a) |
1115 | ret=-EINVAL; | 1053 | { |
1116 | break; | ||
1117 | } | ||
1118 | ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M"); | ||
1119 | 1054 | ||
1120 | /* Allows vivi to use different fps from video std */ | 1055 | return 0; |
1121 | e->frameperiod.numerator = WAKE_NUMERATOR; | 1056 | } |
1122 | e->frameperiod.denominator = WAKE_DENOMINATOR; | ||
1123 | 1057 | ||
1124 | break; | 1058 | /* only one input in this sample driver */ |
1125 | } | 1059 | static int vidioc_enum_input (struct file *file, void *priv, |
1126 | case VIDIOC_G_STD: | 1060 | struct v4l2_input *inp) |
1127 | { | 1061 | { |
1128 | v4l2_std_id *id = arg; | 1062 | if (inp->index != 0) |
1063 | return -EINVAL; | ||
1129 | 1064 | ||
1130 | *id = V4L2_STD_NTSC_M; | 1065 | inp->type = V4L2_INPUT_TYPE_CAMERA; |
1131 | break; | 1066 | inp->std = V4L2_STD_NTSC_M; |
1132 | } | 1067 | strcpy(inp->name,"Camera"); |
1133 | case VIDIOC_S_STD: | ||
1134 | { | ||
1135 | break; | ||
1136 | } | ||
1137 | /* ------ input switching ---------- */ | ||
1138 | case VIDIOC_ENUMINPUT: | ||
1139 | { /* only one input in this sample driver */ | ||
1140 | struct v4l2_input *inp = arg; | ||
1141 | 1068 | ||
1142 | if (inp->index != 0) { | 1069 | return (0); |
1143 | ret=-EINVAL; | 1070 | } |
1144 | break; | ||
1145 | } | ||
1146 | memset(inp, 0, sizeof(*inp)); | ||
1147 | 1071 | ||
1148 | inp->index = 0; | 1072 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
1149 | inp->type = V4L2_INPUT_TYPE_CAMERA; | 1073 | { |
1150 | inp->std = V4L2_STD_NTSC_M; | 1074 | *i = 0; |
1151 | strcpy(inp->name,"Camera"); | ||
1152 | break; | ||
1153 | } | ||
1154 | case VIDIOC_G_INPUT: | ||
1155 | { | ||
1156 | unsigned int *i = arg; | ||
1157 | 1075 | ||
1158 | *i = 0; | 1076 | return (0); |
1159 | break; | 1077 | } |
1160 | } | 1078 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
1161 | case VIDIOC_S_INPUT: | 1079 | { |
1162 | { | 1080 | if (i > 0) |
1163 | unsigned int *i = arg; | 1081 | return -EINVAL; |
1164 | 1082 | ||
1165 | if (*i > 0) | 1083 | return (0); |
1166 | ret=-EINVAL; | 1084 | } |
1167 | break; | ||
1168 | } | ||
1169 | 1085 | ||
1170 | /* --- controls ---------------------------------------------- */ | 1086 | /* --- controls ---------------------------------------------- */ |
1171 | case VIDIOC_QUERYCTRL: | 1087 | static int vidioc_queryctrl (struct file *file, void *priv, |
1172 | { | 1088 | struct v4l2_queryctrl *qc) |
1173 | struct v4l2_queryctrl *qc = arg; | 1089 | { |
1174 | int i; | 1090 | int i; |
1175 | |||
1176 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1177 | if (qc->id && qc->id == vivi_qctrl[i].id) { | ||
1178 | memcpy(qc, &(vivi_qctrl[i]), | ||
1179 | sizeof(*qc)); | ||
1180 | break; | ||
1181 | } | ||
1182 | 1091 | ||
1183 | ret=-EINVAL; | 1092 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) |
1184 | break; | 1093 | if (qc->id && qc->id == vivi_qctrl[i].id) { |
1185 | } | 1094 | memcpy(qc, &(vivi_qctrl[i]), |
1186 | case VIDIOC_G_CTRL: | 1095 | sizeof(*qc)); |
1187 | { | 1096 | return (0); |
1188 | struct v4l2_control *ctrl = arg; | 1097 | } |
1189 | int i; | ||
1190 | 1098 | ||
1191 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | 1099 | return -EINVAL; |
1192 | if (ctrl->id == vivi_qctrl[i].id) { | 1100 | } |
1193 | ctrl->value=qctl_regs[i]; | ||
1194 | break; | ||
1195 | } | ||
1196 | 1101 | ||
1197 | ret=-EINVAL; | 1102 | static int vidioc_g_ctrl (struct file *file, void *priv, |
1198 | break; | 1103 | struct v4l2_control *ctrl) |
1199 | } | 1104 | { |
1200 | case VIDIOC_S_CTRL: | 1105 | int i; |
1201 | { | ||
1202 | struct v4l2_control *ctrl = arg; | ||
1203 | int i; | ||
1204 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1205 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1206 | if (ctrl->value < | ||
1207 | vivi_qctrl[i].minimum | ||
1208 | || ctrl->value > | ||
1209 | vivi_qctrl[i].maximum) { | ||
1210 | ret=-ERANGE; | ||
1211 | break; | ||
1212 | } | ||
1213 | qctl_regs[i]=ctrl->value; | ||
1214 | break; | ||
1215 | } | ||
1216 | ret=-EINVAL; | ||
1217 | break; | ||
1218 | } | ||
1219 | default: | ||
1220 | ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl); | ||
1221 | } | ||
1222 | 1106 | ||
1223 | if (debug) { | 1107 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) |
1224 | if (ret<0) { | 1108 | if (ctrl->id == vivi_qctrl[i].id) { |
1225 | v4l_print_ioctl("vivi(err)", cmd); | 1109 | ctrl->value=qctl_regs[i]; |
1226 | dprintk(1,"errcode=%d\n",ret); | 1110 | return (0); |
1227 | } else if (_IOC_DIR(cmd) & _IOC_READ) | 1111 | } |
1228 | v4l_printk_ioctl_arg("vivi(r)",cmd, arg); | ||
1229 | } | ||
1230 | 1112 | ||
1231 | return ret; | 1113 | return -EINVAL; |
1232 | } | 1114 | } |
1233 | 1115 | static int vidioc_s_ctrl (struct file *file, void *priv, | |
1234 | static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 1116 | struct v4l2_control *ctrl) |
1235 | { | 1117 | { |
1236 | return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl); | 1118 | int i; |
1119 | |||
1120 | for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++) | ||
1121 | if (ctrl->id == vivi_qctrl[i].id) { | ||
1122 | if (ctrl->value < | ||
1123 | vivi_qctrl[i].minimum | ||
1124 | || ctrl->value > | ||
1125 | vivi_qctrl[i].maximum) { | ||
1126 | return (-ERANGE); | ||
1127 | } | ||
1128 | qctl_regs[i]=ctrl->value; | ||
1129 | return (0); | ||
1130 | } | ||
1131 | return -EINVAL; | ||
1237 | } | 1132 | } |
1238 | 1133 | ||
1239 | /* ------------------------------------------------------------------ | 1134 | /* ------------------------------------------------------------------ |
@@ -1255,7 +1150,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1255 | 1150 | ||
1256 | list_for_each(list,&vivi_devlist) { | 1151 | list_for_each(list,&vivi_devlist) { |
1257 | h = list_entry(list, struct vivi_dev, vivi_devlist); | 1152 | h = list_entry(list, struct vivi_dev, vivi_devlist); |
1258 | if (h->video_dev.minor == minor) { | 1153 | if (h->vfd.minor == minor) { |
1259 | dev = h; | 1154 | dev = h; |
1260 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1155 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1261 | } | 1156 | } |
@@ -1264,6 +1159,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1264 | return -ENODEV; | 1159 | return -ENODEV; |
1265 | 1160 | ||
1266 | 1161 | ||
1162 | |||
1267 | /* If more than one user, mutex should be added */ | 1163 | /* If more than one user, mutex should be added */ |
1268 | dev->users++; | 1164 | dev->users++; |
1269 | 1165 | ||
@@ -1279,6 +1175,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1279 | 1175 | ||
1280 | file->private_data = fh; | 1176 | file->private_data = fh; |
1281 | fh->dev = dev; | 1177 | fh->dev = dev; |
1178 | |||
1282 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1179 | fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1283 | fh->fmt = &format; | 1180 | fh->fmt = &format; |
1284 | fh->width = 640; | 1181 | fh->width = 640; |
@@ -1314,7 +1211,7 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1314 | static ssize_t | 1211 | static ssize_t |
1315 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | 1212 | vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) |
1316 | { | 1213 | { |
1317 | struct vivi_fh *fh = file->private_data; | 1214 | struct vivi_fh *fh = file->private_data; |
1318 | 1215 | ||
1319 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 1216 | if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
1320 | if (res_locked(fh->dev)) | 1217 | if (res_locked(fh->dev)) |
@@ -1328,8 +1225,8 @@ vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | |||
1328 | static unsigned int | 1225 | static unsigned int |
1329 | vivi_poll(struct file *file, struct poll_table_struct *wait) | 1226 | vivi_poll(struct file *file, struct poll_table_struct *wait) |
1330 | { | 1227 | { |
1331 | struct vivi_fh *fh = file->private_data; | 1228 | struct vivi_fh *fh = file->private_data; |
1332 | struct vivi_buffer *buf; | 1229 | struct vivi_buffer *buf; |
1333 | 1230 | ||
1334 | dprintk(1,"%s\n",__FUNCTION__); | 1231 | dprintk(1,"%s\n",__FUNCTION__); |
1335 | 1232 | ||
@@ -1358,8 +1255,8 @@ vivi_poll(struct file *file, struct poll_table_struct *wait) | |||
1358 | 1255 | ||
1359 | static int vivi_release(struct inode *inode, struct file *file) | 1256 | static int vivi_release(struct inode *inode, struct file *file) |
1360 | { | 1257 | { |
1361 | struct vivi_fh *fh = file->private_data; | 1258 | struct vivi_fh *fh = file->private_data; |
1362 | struct vivi_dev *dev = fh->dev; | 1259 | struct vivi_dev *dev = fh->dev; |
1363 | struct vivi_dmaqueue *vidq = &dev->vidq; | 1260 | struct vivi_dmaqueue *vidq = &dev->vidq; |
1364 | 1261 | ||
1365 | int minor = iminor(inode); | 1262 | int minor = iminor(inode); |
@@ -1379,7 +1276,7 @@ static int vivi_release(struct inode *inode, struct file *file) | |||
1379 | static int | 1276 | static int |
1380 | vivi_mmap(struct file *file, struct vm_area_struct * vma) | 1277 | vivi_mmap(struct file *file, struct vm_area_struct * vma) |
1381 | { | 1278 | { |
1382 | struct vivi_fh *fh = file->private_data; | 1279 | struct vivi_fh *fh = file->private_data; |
1383 | int ret; | 1280 | int ret; |
1384 | 1281 | ||
1385 | dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); | 1282 | dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma); |
@@ -1400,20 +1297,44 @@ static struct file_operations vivi_fops = { | |||
1400 | .release = vivi_release, | 1297 | .release = vivi_release, |
1401 | .read = vivi_read, | 1298 | .read = vivi_read, |
1402 | .poll = vivi_poll, | 1299 | .poll = vivi_poll, |
1403 | .ioctl = vivi_ioctl, | 1300 | .ioctl = video_ioctl2, /* V4L2 ioctl handler */ |
1404 | .mmap = vivi_mmap, | 1301 | .mmap = vivi_mmap, |
1405 | .llseek = no_llseek, | 1302 | .llseek = no_llseek, |
1406 | }; | 1303 | }; |
1407 | 1304 | ||
1408 | static struct video_device vivi = { | 1305 | static struct video_device vivi = { |
1409 | .name = "VTM Virtual Video Capture Board", | 1306 | .name = "vivi", |
1410 | .type = VID_TYPE_CAPTURE, | 1307 | .type = VID_TYPE_CAPTURE, |
1411 | .hardware = 0, | 1308 | .hardware = 0, |
1412 | .fops = &vivi_fops, | 1309 | .fops = &vivi_fops, |
1413 | .minor = -1, | 1310 | .minor = -1, |
1414 | // .release = video_device_release, | 1311 | // .release = video_device_release, |
1312 | |||
1313 | .vidioc_querycap = vidioc_querycap, | ||
1314 | .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, | ||
1315 | .vidioc_g_fmt_cap = vidioc_g_fmt_cap, | ||
1316 | .vidioc_try_fmt_cap = vidioc_try_fmt_cap, | ||
1317 | .vidioc_s_fmt_cap = vidioc_s_fmt_cap, | ||
1318 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1319 | .vidioc_querybuf = vidioc_querybuf, | ||
1320 | .vidioc_qbuf = vidioc_qbuf, | ||
1321 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1322 | .vidioc_s_std = vidioc_s_std, | ||
1323 | .vidioc_enum_input = vidioc_enum_input, | ||
1324 | .vidioc_g_input = vidioc_g_input, | ||
1325 | .vidioc_s_input = vidioc_s_input, | ||
1326 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1327 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1328 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1329 | .vidioc_streamon = vidioc_streamon, | ||
1330 | .vidioc_streamoff = vidioc_streamoff, | ||
1331 | #ifdef HAVE_V4L1 | ||
1332 | .vidiocgmbuf = vidiocgmbuf, | ||
1333 | #endif | ||
1334 | .tvnorms = tvnorms, | ||
1335 | .tvnormsize = ARRAY_SIZE(tvnorms), | ||
1415 | }; | 1336 | }; |
1416 | /* ------------------------------------------------------------------ | 1337 | /* ----------------------------------------------------------------- |
1417 | Initialization and module stuff | 1338 | Initialization and module stuff |
1418 | ------------------------------------------------------------------*/ | 1339 | ------------------------------------------------------------------*/ |
1419 | 1340 | ||
@@ -1457,3 +1378,16 @@ static void __exit vivi_exit(void) | |||
1457 | 1378 | ||
1458 | module_init(vivi_init); | 1379 | module_init(vivi_init); |
1459 | module_exit(vivi_exit); | 1380 | module_exit(vivi_exit); |
1381 | |||
1382 | MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board"); | ||
1383 | MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol"); | ||
1384 | MODULE_LICENSE("Dual BSD/GPL"); | ||
1385 | |||
1386 | module_param(video_nr, int, 0); | ||
1387 | |||
1388 | module_param_named(debug,vivi.debug, int, 0644); | ||
1389 | MODULE_PARM_DESC(debug,"activates debug info"); | ||
1390 | |||
1391 | module_param(vid_limit,int,0644); | ||
1392 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
1393 | |||