aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry MERLE <thierry.merle@free.fr>2007-02-07 08:13:11 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-02-21 10:35:19 -0500
commit6f78e186fe5d29dbff5e34f950adb573c4808de4 (patch)
tree23297d74fceeaa3b9668fda9a429c17c57107213
parentc65eeaab1f04d1113b5c4fb21f7f61ded795d2bb (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.c35
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c57
-rw-r--r--drivers/media/video/usbvision/usbvision.h3
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 */
1857int usbvision_frames_alloc(struct usb_usbvision *usbvision) 1857int 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)
1897void usbvision_frames_free(struct usb_usbvision *usbvision) 1903void 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);
490int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, 491int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
491 unsigned char value); 492 unsigned char value);
492 493
493int usbvision_frames_alloc(struct usb_usbvision *usbvision); 494int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames);
494void usbvision_frames_free(struct usb_usbvision *usbvision); 495void usbvision_frames_free(struct usb_usbvision *usbvision);
495int usbvision_scratch_alloc(struct usb_usbvision *usbvision); 496int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
496void usbvision_scratch_free(struct usb_usbvision *usbvision); 497void usbvision_scratch_free(struct usb_usbvision *usbvision);