diff options
author | Thierry MERLE <thierry.merle@free.fr> | 2007-02-07 08:13:11 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-02-21 10:35:19 -0500 |
commit | 6f78e186fe5d29dbff5e34f950adb573c4808de4 (patch) | |
tree | 23297d74fceeaa3b9668fda9a429c17c57107213 | |
parent | c65eeaab1f04d1113b5c4fb21f7f61ded795d2bb (diff) |
V4L/DVB (5205): Usbvision: dynamic allocation for frames
- fix decoder route output
- dynamic frame buffer allocation
Signed-off-by: Thierry MERLE <thierry.merle@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | drivers/media/video/usbvision/usbvision-core.c | 35 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision-video.c | 57 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision.h | 3 |
3 files changed, 60 insertions, 35 deletions
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index 42f495c9f5ff..d4fcd5736ba9 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c | |||
@@ -1852,28 +1852,33 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, | |||
1852 | 1852 | ||
1853 | /* | 1853 | /* |
1854 | * usbvision_frames_alloc | 1854 | * usbvision_frames_alloc |
1855 | * allocate the maximum frames this driver can manage | 1855 | * allocate the required frames |
1856 | */ | 1856 | */ |
1857 | int usbvision_frames_alloc(struct usb_usbvision *usbvision) | 1857 | int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames) |
1858 | { | 1858 | { |
1859 | int i; | 1859 | int i; |
1860 | 1860 | ||
1861 | /* Allocate memory for the frame buffers */ | 1861 | /*needs to be page aligned cause the buffers can be mapped individually! */ |
1862 | usbvision->max_frame_size = MAX_FRAME_SIZE; | 1862 | usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth * |
1863 | usbvision->fbuf_size = USBVISION_NUMFRAMES * usbvision->max_frame_size; | 1863 | usbvision->curheight * |
1864 | usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size); | 1864 | usbvision->palette.bytes_per_pixel); |
1865 | 1865 | ||
1866 | if(usbvision->fbuf == NULL) { | 1866 | /* Try to do my best to allocate the frames the user want in the remaining memory */ |
1867 | err("%s: unable to allocate %d bytes for fbuf ", | 1867 | usbvision->num_frames = number_of_frames; |
1868 | __FUNCTION__, usbvision->fbuf_size); | 1868 | while (usbvision->num_frames > 0) { |
1869 | return -ENOMEM; | 1869 | usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size; |
1870 | if((usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size))) { | ||
1871 | break; | ||
1872 | } | ||
1873 | usbvision->num_frames--; | ||
1870 | } | 1874 | } |
1875 | |||
1871 | spin_lock_init(&usbvision->queue_lock); | 1876 | spin_lock_init(&usbvision->queue_lock); |
1872 | init_waitqueue_head(&usbvision->wait_frame); | 1877 | init_waitqueue_head(&usbvision->wait_frame); |
1873 | init_waitqueue_head(&usbvision->wait_stream); | 1878 | init_waitqueue_head(&usbvision->wait_stream); |
1874 | 1879 | ||
1875 | /* Allocate all buffers */ | 1880 | /* Allocate all buffers */ |
1876 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | 1881 | for (i = 0; i < usbvision->num_frames; i++) { |
1877 | usbvision->frame[i].index = i; | 1882 | usbvision->frame[i].index = i; |
1878 | usbvision->frame[i].grabstate = FrameState_Unused; | 1883 | usbvision->frame[i].grabstate = FrameState_Unused; |
1879 | usbvision->frame[i].data = usbvision->fbuf + | 1884 | usbvision->frame[i].data = usbvision->fbuf + |
@@ -1887,7 +1892,8 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision) | |||
1887 | usbvision->frame[i].height = usbvision->curheight; | 1892 | usbvision->frame[i].height = usbvision->curheight; |
1888 | usbvision->frame[i].bytes_read = 0; | 1893 | usbvision->frame[i].bytes_read = 0; |
1889 | } | 1894 | } |
1890 | return 0; | 1895 | PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",usbvision->num_frames,usbvision->max_frame_size); |
1896 | return usbvision->num_frames; | ||
1891 | } | 1897 | } |
1892 | 1898 | ||
1893 | /* | 1899 | /* |
@@ -1897,9 +1903,13 @@ int usbvision_frames_alloc(struct usb_usbvision *usbvision) | |||
1897 | void usbvision_frames_free(struct usb_usbvision *usbvision) | 1903 | void usbvision_frames_free(struct usb_usbvision *usbvision) |
1898 | { | 1904 | { |
1899 | /* Have to free all that memory */ | 1905 | /* Have to free all that memory */ |
1906 | PDEBUG(DBG_FUNC, "free %d frames",usbvision->num_frames); | ||
1907 | |||
1900 | if (usbvision->fbuf != NULL) { | 1908 | if (usbvision->fbuf != NULL) { |
1901 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); | 1909 | usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size); |
1902 | usbvision->fbuf = NULL; | 1910 | usbvision->fbuf = NULL; |
1911 | |||
1912 | usbvision->num_frames = 0; | ||
1903 | } | 1913 | } |
1904 | } | 1914 | } |
1905 | /* | 1915 | /* |
@@ -2490,6 +2500,7 @@ int usbvision_muxsel(struct usb_usbvision *usbvision, int channel) | |||
2490 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); | 2500 | RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs); |
2491 | usbvision->ctl_input = channel; | 2501 | usbvision->ctl_input = channel; |
2492 | route.input = SAA7115_COMPOSITE1; | 2502 | route.input = SAA7115_COMPOSITE1; |
2503 | route.output = 0; | ||
2493 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); | 2504 | call_i2c_clients(usbvision, VIDIOC_INT_S_VIDEO_ROUTING,&route); |
2494 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); | 2505 | call_i2c_clients(usbvision, VIDIOC_S_INPUT, &usbvision->ctl_input); |
2495 | 2506 | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 6a61ebcdf130..cfbfda47ec4f 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -391,19 +391,14 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file) | |||
391 | if (usbvision->user) | 391 | if (usbvision->user) |
392 | errCode = -EBUSY; | 392 | errCode = -EBUSY; |
393 | else { | 393 | else { |
394 | /* Allocate memory for the frame buffers */ | 394 | /* Allocate memory for the scratch ring buffer */ |
395 | errCode = usbvision_frames_alloc(usbvision); | 395 | errCode = usbvision_scratch_alloc(usbvision); |
396 | if(!errCode) { | 396 | if (isocMode==ISOC_MODE_COMPRESS) { |
397 | /* Allocate memory for the scratch ring buffer */ | 397 | /* Allocate intermediate decompression buffers only if needed */ |
398 | errCode = usbvision_scratch_alloc(usbvision); | 398 | errCode = usbvision_decompress_alloc(usbvision); |
399 | if ((!errCode) && (isocMode==ISOC_MODE_COMPRESS)) { | ||
400 | /* Allocate intermediate decompression buffers only if needed */ | ||
401 | errCode = usbvision_decompress_alloc(usbvision); | ||
402 | } | ||
403 | } | 399 | } |
404 | if (errCode) { | 400 | if (errCode) { |
405 | /* Deallocate all buffers if trouble */ | 401 | /* Deallocate all buffers if trouble */ |
406 | usbvision_frames_free(usbvision); | ||
407 | usbvision_scratch_free(usbvision); | 402 | usbvision_scratch_free(usbvision); |
408 | usbvision_decompress_free(usbvision); | 403 | usbvision_decompress_free(usbvision); |
409 | } | 404 | } |
@@ -476,6 +471,7 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file) | |||
476 | 471 | ||
477 | usbvision_decompress_free(usbvision); | 472 | usbvision_decompress_free(usbvision); |
478 | usbvision_frames_free(usbvision); | 473 | usbvision_frames_free(usbvision); |
474 | usbvision_empty_framequeues(usbvision); | ||
479 | usbvision_scratch_free(usbvision); | 475 | usbvision_scratch_free(usbvision); |
480 | 476 | ||
481 | usbvision->user--; | 477 | usbvision->user--; |
@@ -809,7 +805,9 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
809 | return ret; | 805 | return ret; |
810 | } | 806 | } |
811 | 807 | ||
808 | usbvision_frames_free(usbvision); | ||
812 | usbvision_empty_framequeues(usbvision); | 809 | usbvision_empty_framequeues(usbvision); |
810 | vr->count = usbvision_frames_alloc(usbvision,vr->count); | ||
813 | 811 | ||
814 | usbvision->curFrame = NULL; | 812 | usbvision->curFrame = NULL; |
815 | 813 | ||
@@ -826,7 +824,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
826 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | 824 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { |
827 | return -EINVAL; | 825 | return -EINVAL; |
828 | } | 826 | } |
829 | if(vb->index>=USBVISION_NUMFRAMES) { | 827 | if(vb->index>=usbvision->num_frames) { |
830 | return -EINVAL; | 828 | return -EINVAL; |
831 | } | 829 | } |
832 | // Updating the corresponding frame state | 830 | // Updating the corresponding frame state |
@@ -840,7 +838,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
840 | vb->flags |= V4L2_BUF_FLAG_MAPPED; | 838 | vb->flags |= V4L2_BUF_FLAG_MAPPED; |
841 | vb->memory = V4L2_MEMORY_MMAP; | 839 | vb->memory = V4L2_MEMORY_MMAP; |
842 | 840 | ||
843 | vb->m.offset = vb->index*usbvision->max_frame_size; | 841 | vb->m.offset = vb->index*PAGE_ALIGN(usbvision->max_frame_size); |
844 | 842 | ||
845 | vb->memory = V4L2_MEMORY_MMAP; | 843 | vb->memory = V4L2_MEMORY_MMAP; |
846 | vb->field = V4L2_FIELD_NONE; | 844 | vb->field = V4L2_FIELD_NONE; |
@@ -859,7 +857,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
859 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { | 857 | if(vb->type != V4L2_CAP_VIDEO_CAPTURE) { |
860 | return -EINVAL; | 858 | return -EINVAL; |
861 | } | 859 | } |
862 | if(vb->index>=USBVISION_NUMFRAMES) { | 860 | if(vb->index>=usbvision->num_frames) { |
863 | return -EINVAL; | 861 | return -EINVAL; |
864 | } | 862 | } |
865 | 863 | ||
@@ -1029,6 +1027,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
1029 | if ((ret = usbvision_stream_interrupt(usbvision))) | 1027 | if ((ret = usbvision_stream_interrupt(usbvision))) |
1030 | return ret; | 1028 | return ret; |
1031 | } | 1029 | } |
1030 | usbvision_frames_free(usbvision); | ||
1032 | usbvision_empty_framequeues(usbvision); | 1031 | usbvision_empty_framequeues(usbvision); |
1033 | 1032 | ||
1034 | usbvision->curFrame = NULL; | 1033 | usbvision->curFrame = NULL; |
@@ -1075,12 +1074,24 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf, | |||
1075 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) | 1074 | if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL)) |
1076 | return -EFAULT; | 1075 | return -EFAULT; |
1077 | 1076 | ||
1078 | /* no stream is running, make it running ! */ | 1077 | /* This entry point is compatible with the mmap routines so that a user can do either |
1079 | usbvision->streaming = Stream_On; | 1078 | VIDIOC_QBUF/VIDIOC_DQBUF to get frames or call read on the device. */ |
1080 | call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); | 1079 | if(!usbvision->num_frames) { |
1080 | /* First, allocate some frames to work with if this has not been done with | ||
1081 | VIDIOC_REQBUF */ | ||
1082 | usbvision_frames_free(usbvision); | ||
1083 | usbvision_empty_framequeues(usbvision); | ||
1084 | usbvision_frames_alloc(usbvision,USBVISION_NUMFRAMES); | ||
1085 | } | ||
1086 | |||
1087 | if(usbvision->streaming != Stream_On) { | ||
1088 | /* no stream is running, make it running ! */ | ||
1089 | usbvision->streaming = Stream_On; | ||
1090 | call_i2c_clients(usbvision,VIDIOC_STREAMON , NULL); | ||
1091 | } | ||
1081 | 1092 | ||
1082 | /* First, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ | 1093 | /* Then, enqueue as many frames as possible (like a user of VIDIOC_QBUF would do) */ |
1083 | for(i=0;i<USBVISION_NUMFRAMES;i++) { | 1094 | for(i=0;i<usbvision->num_frames;i++) { |
1084 | frame = &usbvision->frame[i]; | 1095 | frame = &usbvision->frame[i]; |
1085 | if(frame->grabstate == FrameState_Unused) { | 1096 | if(frame->grabstate == FrameState_Unused) { |
1086 | /* Mark it as ready and enqueue frame */ | 1097 | /* Mark it as ready and enqueue frame */ |
@@ -1157,6 +1168,8 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
1157 | struct video_device *dev = video_devdata(file); | 1168 | struct video_device *dev = video_devdata(file); |
1158 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); | 1169 | struct usb_usbvision *usbvision = (struct usb_usbvision *) video_get_drvdata(dev); |
1159 | 1170 | ||
1171 | PDEBUG(DBG_MMAP, "mmap"); | ||
1172 | |||
1160 | down(&usbvision->lock); | 1173 | down(&usbvision->lock); |
1161 | 1174 | ||
1162 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { | 1175 | if (!USBVISION_IS_OPERATIONAL(usbvision)) { |
@@ -1165,16 +1178,16 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | |||
1165 | } | 1178 | } |
1166 | 1179 | ||
1167 | if (!(vma->vm_flags & VM_WRITE) || | 1180 | if (!(vma->vm_flags & VM_WRITE) || |
1168 | size != PAGE_ALIGN(usbvision->curwidth*usbvision->curheight*usbvision->palette.bytes_per_pixel)) { | 1181 | size != PAGE_ALIGN(usbvision->max_frame_size)) { |
1169 | up(&usbvision->lock); | 1182 | up(&usbvision->lock); |
1170 | return -EINVAL; | 1183 | return -EINVAL; |
1171 | } | 1184 | } |
1172 | 1185 | ||
1173 | for (i = 0; i < USBVISION_NUMFRAMES; i++) { | 1186 | for (i = 0; i < usbvision->num_frames; i++) { |
1174 | if (((usbvision->max_frame_size*i) >> PAGE_SHIFT) == vma->vm_pgoff) | 1187 | if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) == vma->vm_pgoff) |
1175 | break; | 1188 | break; |
1176 | } | 1189 | } |
1177 | if (i == USBVISION_NUMFRAMES) { | 1190 | if (i == usbvision->num_frames) { |
1178 | PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); | 1191 | PDEBUG(DBG_MMAP, "mmap: user supplied mapping address is out of range"); |
1179 | up(&usbvision->lock); | 1192 | up(&usbvision->lock); |
1180 | return -EINVAL; | 1193 | return -EINVAL; |
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index a316871b79a0..0e2b55699860 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -421,6 +421,7 @@ struct usb_usbvision { | |||
421 | wait_queue_head_t wait_stream; /* Processes waiting */ | 421 | wait_queue_head_t wait_stream; /* Processes waiting */ |
422 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header | 422 | struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header |
423 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer | 423 | struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer |
424 | int num_frames; // number of frames allocated | ||
424 | struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering | 425 | struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering |
425 | volatile int remove_pending; /* If set then about to exit */ | 426 | volatile int remove_pending; /* If set then about to exit */ |
426 | 427 | ||
@@ -490,7 +491,7 @@ int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg); | |||
490 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, | 491 | int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, |
491 | unsigned char value); | 492 | unsigned char value); |
492 | 493 | ||
493 | int usbvision_frames_alloc(struct usb_usbvision *usbvision); | 494 | int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames); |
494 | void usbvision_frames_free(struct usb_usbvision *usbvision); | 495 | void usbvision_frames_free(struct usb_usbvision *usbvision); |
495 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision); | 496 | int usbvision_scratch_alloc(struct usb_usbvision *usbvision); |
496 | void usbvision_scratch_free(struct usb_usbvision *usbvision); | 497 | void usbvision_scratch_free(struct usb_usbvision *usbvision); |