diff options
Diffstat (limited to 'drivers/media/video/vivi.c')
-rw-r--r-- | drivers/media/video/vivi.c | 178 |
1 files changed, 8 insertions, 170 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 3ef4d0159c33..f6d3a9460ccc 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/random.h> | 26 | #include <linux/random.h> |
27 | #include <linux/version.h> | 27 | #include <linux/version.h> |
28 | #include <linux/mutex.h> | ||
28 | #include <linux/videodev2.h> | 29 | #include <linux/videodev2.h> |
29 | #include <linux/dma-mapping.h> | 30 | #include <linux/dma-mapping.h> |
30 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | 31 | #ifdef CONFIG_VIDEO_V4L1_COMPAT |
@@ -145,9 +146,6 @@ struct vivi_buffer { | |||
145 | 146 | ||
146 | struct vivi_fmt *fmt; | 147 | struct vivi_fmt *fmt; |
147 | 148 | ||
148 | #ifdef CONFIG_VIVI_SCATTER | ||
149 | struct sg_to_addr *to_addr; | ||
150 | #endif | ||
151 | }; | 149 | }; |
152 | 150 | ||
153 | struct vivi_dmaqueue { | 151 | struct vivi_dmaqueue { |
@@ -168,7 +166,7 @@ static LIST_HEAD(vivi_devlist); | |||
168 | struct vivi_dev { | 166 | struct vivi_dev { |
169 | struct list_head vivi_devlist; | 167 | struct list_head vivi_devlist; |
170 | 168 | ||
171 | struct semaphore lock; | 169 | struct mutex lock; |
172 | 170 | ||
173 | int users; | 171 | int users; |
174 | 172 | ||
@@ -232,68 +230,13 @@ static u8 bars[8][3] = { | |||
232 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 | 230 | #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15 |
233 | #define TSTAMP_MIN_X 64 | 231 | #define TSTAMP_MIN_X 64 |
234 | 232 | ||
235 | #ifdef CONFIG_VIVI_SCATTER | ||
236 | static void prep_to_addr(struct sg_to_addr to_addr[], | ||
237 | struct videobuf_buffer *vb) | ||
238 | { | ||
239 | int i, pos=0; | ||
240 | |||
241 | for (i=0;i<vb->dma.nr_pages;i++) { | ||
242 | to_addr[i].sg=&vb->dma.sglist[i]; | ||
243 | to_addr[i].pos=pos; | ||
244 | pos += vb->dma.sglist[i].length; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[]) | ||
249 | { | ||
250 | int p1=0,p2=pages-1,p3=pages/2; | ||
251 | |||
252 | /* Sanity test */ | ||
253 | BUG_ON (pos>=to_addr[p2].pos+to_addr[p2].sg->length); | ||
254 | |||
255 | while (p1+1<p2) { | ||
256 | if (pos < to_addr[p3].pos) { | ||
257 | p2=p3; | ||
258 | } else { | ||
259 | p1=p3; | ||
260 | } | ||
261 | p3=(p1+p2)/2; | ||
262 | } | ||
263 | if (pos >= to_addr[p2].pos) | ||
264 | p1=p2; | ||
265 | |||
266 | return (p1); | ||
267 | } | ||
268 | #endif | ||
269 | 233 | ||
270 | #ifdef CONFIG_VIVI_SCATTER | ||
271 | static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax, | ||
272 | int hmax, int line, char *timestr) | ||
273 | #else | ||
274 | static void gen_line(char *basep,int inipos,int wmax, | 234 | static void gen_line(char *basep,int inipos,int wmax, |
275 | int hmax, int line, char *timestr) | 235 | int hmax, int line, char *timestr) |
276 | #endif | ||
277 | { | 236 | { |
278 | int w,i,j,pos=inipos,y; | 237 | int w,i,j,pos=inipos,y; |
279 | char *p,*s; | 238 | char *p,*s; |
280 | u8 chr,r,g,b,color; | 239 | u8 chr,r,g,b,color; |
281 | #ifdef CONFIG_VIVI_SCATTER | ||
282 | int pgpos,oldpg; | ||
283 | char *basep; | ||
284 | struct page *pg; | ||
285 | |||
286 | unsigned long flags; | ||
287 | spinlock_t spinlock; | ||
288 | |||
289 | spin_lock_init(&spinlock); | ||
290 | |||
291 | /* Get first addr pointed to pixel position */ | ||
292 | oldpg=get_addr_pos(pos,pages,to_addr); | ||
293 | pg=pfn_to_page(sg_dma_address(to_addr[oldpg].sg) >> PAGE_SHIFT); | ||
294 | spin_lock_irqsave(&spinlock,flags); | ||
295 | basep = kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[oldpg].sg->offset; | ||
296 | #endif | ||
297 | 240 | ||
298 | /* We will just duplicate the second pixel at the packet */ | 241 | /* We will just duplicate the second pixel at the packet */ |
299 | wmax/=2; | 242 | wmax/=2; |
@@ -305,18 +248,7 @@ static void gen_line(char *basep,int inipos,int wmax, | |||
305 | b=bars[w*7/wmax][2]; | 248 | b=bars[w*7/wmax][2]; |
306 | 249 | ||
307 | for (color=0;color<4;color++) { | 250 | for (color=0;color<4;color++) { |
308 | #ifdef CONFIG_VIVI_SCATTER | ||
309 | pgpos=get_addr_pos(pos,pages,to_addr); | ||
310 | if (pgpos!=oldpg) { | ||
311 | pg=pfn_to_page(sg_dma_address(to_addr[pgpos].sg) >> PAGE_SHIFT); | ||
312 | kunmap_atomic(basep, KM_BOUNCE_READ); | ||
313 | basep= kmap_atomic(pg, KM_BOUNCE_READ)+to_addr[pgpos].sg->offset; | ||
314 | oldpg=pgpos; | ||
315 | } | ||
316 | p=basep+pos-to_addr[pgpos].pos; | ||
317 | #else | ||
318 | p=basep+pos; | 251 | p=basep+pos; |
319 | #endif | ||
320 | 252 | ||
321 | switch (color) { | 253 | switch (color) { |
322 | case 0: | 254 | case 0: |
@@ -361,23 +293,7 @@ static void gen_line(char *basep,int inipos,int wmax, | |||
361 | 293 | ||
362 | pos=inipos+j*2; | 294 | pos=inipos+j*2; |
363 | for (color=0;color<4;color++) { | 295 | for (color=0;color<4;color++) { |
364 | #ifdef CONFIG_VIVI_SCATTER | ||
365 | pgpos=get_addr_pos(pos,pages,to_addr); | ||
366 | if (pgpos!=oldpg) { | ||
367 | pg=pfn_to_page(sg_dma_address( | ||
368 | to_addr[pgpos].sg) | ||
369 | >> PAGE_SHIFT); | ||
370 | kunmap_atomic(basep, | ||
371 | KM_BOUNCE_READ); | ||
372 | basep= kmap_atomic(pg, | ||
373 | KM_BOUNCE_READ)+ | ||
374 | to_addr[pgpos].sg->offset; | ||
375 | oldpg=pgpos; | ||
376 | } | ||
377 | p=basep+pos-to_addr[pgpos].pos; | ||
378 | #else | ||
379 | p=basep+pos; | 296 | p=basep+pos; |
380 | #endif | ||
381 | 297 | ||
382 | y=TO_Y(r,g,b); | 298 | y=TO_Y(r,g,b); |
383 | 299 | ||
@@ -402,12 +318,7 @@ static void gen_line(char *basep,int inipos,int wmax, | |||
402 | 318 | ||
403 | 319 | ||
404 | end: | 320 | end: |
405 | #ifdef CONFIG_VIVI_SCATTER | ||
406 | kunmap_atomic(basep, KM_BOUNCE_READ); | ||
407 | spin_unlock_irqrestore(&spinlock,flags); | ||
408 | #else | ||
409 | return; | 321 | return; |
410 | #endif | ||
411 | } | 322 | } |
412 | static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | 323 | static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) |
413 | { | 324 | { |
@@ -415,35 +326,16 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | |||
415 | int hmax = buf->vb.height; | 326 | int hmax = buf->vb.height; |
416 | int wmax = buf->vb.width; | 327 | int wmax = buf->vb.width; |
417 | struct timeval ts; | 328 | struct timeval ts; |
418 | #ifdef CONFIG_VIVI_SCATTER | ||
419 | struct sg_to_addr *to_addr=buf->to_addr; | ||
420 | struct videobuf_buffer *vb=&buf->vb; | ||
421 | #else | ||
422 | char *tmpbuf; | 329 | char *tmpbuf; |
423 | #endif | ||
424 | |||
425 | #ifdef CONFIG_VIVI_SCATTER | ||
426 | /* Test if DMA mapping is ready */ | ||
427 | if (!sg_dma_address(&vb->dma.sglist[0])) | ||
428 | return; | ||
429 | |||
430 | prep_to_addr(to_addr,vb); | ||
431 | 330 | ||
432 | /* Check if there is enough memory */ | ||
433 | BUG_ON(buf->vb.dma.nr_pages << PAGE_SHIFT < (buf->vb.width*buf->vb.height)*2); | ||
434 | #else | ||
435 | if (buf->vb.dma.varea) { | 331 | if (buf->vb.dma.varea) { |
436 | tmpbuf=kmalloc (wmax*2, GFP_KERNEL); | 332 | tmpbuf=kmalloc (wmax*2, GFP_KERNEL); |
437 | } else { | 333 | } else { |
438 | tmpbuf=buf->vb.dma.vmalloc; | 334 | tmpbuf=buf->vb.dma.vmalloc; |
439 | } | 335 | } |
440 | 336 | ||
441 | #endif | ||
442 | 337 | ||
443 | for (h=0;h<hmax;h++) { | 338 | for (h=0;h<hmax;h++) { |
444 | #ifdef CONFIG_VIVI_SCATTER | ||
445 | gen_line(to_addr,pos,vb->dma.nr_pages,wmax,hmax,h,dev->timestr); | ||
446 | #else | ||
447 | if (buf->vb.dma.varea) { | 339 | if (buf->vb.dma.varea) { |
448 | gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr); | 340 | gen_line(tmpbuf,0,wmax,hmax,h,dev->timestr); |
449 | /* FIXME: replacing to __copy_to_user */ | 341 | /* FIXME: replacing to __copy_to_user */ |
@@ -452,7 +344,6 @@ static void vivi_fillbuff(struct vivi_dev *dev,struct vivi_buffer *buf) | |||
452 | } else { | 344 | } else { |
453 | gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr); | 345 | gen_line(tmpbuf,pos,wmax,hmax,h,dev->timestr); |
454 | } | 346 | } |
455 | #endif | ||
456 | pos += wmax*2; | 347 | pos += wmax*2; |
457 | } | 348 | } |
458 | 349 | ||
@@ -718,11 +609,6 @@ static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf) | |||
718 | if (in_interrupt()) | 609 | if (in_interrupt()) |
719 | BUG(); | 610 | BUG(); |
720 | 611 | ||
721 | #ifdef CONFIG_VIVI_SCATTER | ||
722 | /*FIXME: Maybe a spinlock is required here */ | ||
723 | kfree(buf->to_addr); | ||
724 | buf->to_addr=NULL; | ||
725 | #endif | ||
726 | 612 | ||
727 | videobuf_waiton(&buf->vb,0,0); | 613 | videobuf_waiton(&buf->vb,0,0); |
728 | videobuf_dma_unmap(vq, &buf->vb.dma); | 614 | videobuf_dma_unmap(vq, &buf->vb.dma); |
@@ -768,12 +654,6 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
768 | 654 | ||
769 | buf->vb.state = STATE_PREPARED; | 655 | buf->vb.state = STATE_PREPARED; |
770 | 656 | ||
771 | #ifdef CONFIG_VIVI_SCATTER | ||
772 | if (NULL == (buf->to_addr = kmalloc(sizeof(*buf->to_addr) * vb->dma.nr_pages,GFP_KERNEL))) { | ||
773 | rc=-ENOMEM; | ||
774 | goto fail; | ||
775 | } | ||
776 | #endif | ||
777 | return 0; | 657 | return 0; |
778 | 658 | ||
779 | fail: | 659 | fail: |
@@ -838,40 +718,6 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb | |||
838 | free_buffer(vq,buf); | 718 | free_buffer(vq,buf); |
839 | } | 719 | } |
840 | 720 | ||
841 | #ifdef CONFIG_VIVI_SCATTER | ||
842 | static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents, | ||
843 | int direction) | ||
844 | { | ||
845 | int i; | ||
846 | |||
847 | dprintk(1,"%s, number of pages=%d\n",__FUNCTION__,nents); | ||
848 | BUG_ON(direction == DMA_NONE); | ||
849 | |||
850 | for (i = 0; i < nents; i++ ) { | ||
851 | BUG_ON(!sg[i].page); | ||
852 | |||
853 | sg_dma_address(&sg[i]) = page_to_phys(sg[i].page) + sg[i].offset; | ||
854 | } | ||
855 | |||
856 | return nents; | ||
857 | } | ||
858 | |||
859 | static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages, | ||
860 | int direction) | ||
861 | { | ||
862 | dprintk(1,"%s\n",__FUNCTION__); | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages, | ||
867 | int direction) | ||
868 | { | ||
869 | // dprintk(1,"%s\n",__FUNCTION__); | ||
870 | |||
871 | // flush_write_buffers(); | ||
872 | return 0; | ||
873 | } | ||
874 | #endif | ||
875 | 721 | ||
876 | static struct videobuf_queue_ops vivi_video_qops = { | 722 | static struct videobuf_queue_ops vivi_video_qops = { |
877 | .buf_setup = buffer_setup, | 723 | .buf_setup = buffer_setup, |
@@ -893,16 +739,16 @@ static struct videobuf_queue_ops vivi_video_qops = { | |||
893 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) | 739 | static int res_get(struct vivi_dev *dev, struct vivi_fh *fh) |
894 | { | 740 | { |
895 | /* is it free? */ | 741 | /* is it free? */ |
896 | down(&dev->lock); | 742 | mutex_lock(&dev->lock); |
897 | if (dev->resources) { | 743 | if (dev->resources) { |
898 | /* no, someone else uses it */ | 744 | /* no, someone else uses it */ |
899 | up(&dev->lock); | 745 | mutex_unlock(&dev->lock); |
900 | return 0; | 746 | return 0; |
901 | } | 747 | } |
902 | /* it's free, grab it */ | 748 | /* it's free, grab it */ |
903 | dev->resources =1; | 749 | dev->resources =1; |
904 | dprintk(1,"res: get\n"); | 750 | dprintk(1,"res: get\n"); |
905 | up(&dev->lock); | 751 | mutex_unlock(&dev->lock); |
906 | return 1; | 752 | return 1; |
907 | } | 753 | } |
908 | 754 | ||
@@ -913,10 +759,10 @@ static int res_locked(struct vivi_dev *dev) | |||
913 | 759 | ||
914 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) | 760 | static void res_free(struct vivi_dev *dev, struct vivi_fh *fh) |
915 | { | 761 | { |
916 | down(&dev->lock); | 762 | mutex_lock(&dev->lock); |
917 | dev->resources = 0; | 763 | dev->resources = 0; |
918 | dprintk(1,"res: put\n"); | 764 | dprintk(1,"res: put\n"); |
919 | up(&dev->lock); | 765 | mutex_lock(&dev->lock); |
920 | } | 766 | } |
921 | 767 | ||
922 | /* ------------------------------------------------------------------ | 768 | /* ------------------------------------------------------------------ |
@@ -1260,19 +1106,11 @@ static int vivi_open(struct inode *inode, struct file *file) | |||
1260 | sprintf(dev->timestr,"%02d:%02d:%02d:%03d", | 1106 | sprintf(dev->timestr,"%02d:%02d:%02d:%03d", |
1261 | dev->h,dev->m,dev->s,(dev->us+500)/1000); | 1107 | dev->h,dev->m,dev->s,(dev->us+500)/1000); |
1262 | 1108 | ||
1263 | #ifdef CONFIG_VIVI_SCATTER | ||
1264 | videobuf_queue_init(&fh->vb_vidq,VIDEOBUF_DMA_SCATTER, &vivi_video_qops, | ||
1265 | NULL, NULL, | ||
1266 | fh->type, | ||
1267 | V4L2_FIELD_INTERLACED, | ||
1268 | sizeof(struct vivi_buffer),fh); | ||
1269 | #else | ||
1270 | videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, | 1109 | videobuf_queue_init(&fh->vb_vidq, &vivi_video_qops, |
1271 | NULL, NULL, | 1110 | NULL, NULL, |
1272 | fh->type, | 1111 | fh->type, |
1273 | V4L2_FIELD_INTERLACED, | 1112 | V4L2_FIELD_INTERLACED, |
1274 | sizeof(struct vivi_buffer),fh); | 1113 | sizeof(struct vivi_buffer),fh); |
1275 | #endif | ||
1276 | 1114 | ||
1277 | return 0; | 1115 | return 0; |
1278 | } | 1116 | } |
@@ -1423,7 +1261,7 @@ static int __init vivi_init(void) | |||
1423 | init_waitqueue_head(&dev->vidq.wq); | 1261 | init_waitqueue_head(&dev->vidq.wq); |
1424 | 1262 | ||
1425 | /* initialize locks */ | 1263 | /* initialize locks */ |
1426 | init_MUTEX(&dev->lock); | 1264 | mutex_init(&dev->lock); |
1427 | 1265 | ||
1428 | dev->vidq.timeout.function = vivi_vid_timeout; | 1266 | dev->vidq.timeout.function = vivi_vid_timeout; |
1429 | dev->vidq.timeout.data = (unsigned long)dev; | 1267 | dev->vidq.timeout.data = (unsigned long)dev; |