aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Liu <lliubbo@gmail.com>2011-04-29 06:11:35 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 11:16:45 -0400
commit7296944759c41001122fc95110468a1a572352cd (patch)
tree94fe97dd4f5d00d332e77fec0974ebee8e59f377
parentecc6517d947e91f02eb5a3a055f524122846f84e (diff)
[media] uvcvideo: Add support for NOMMU arch
Add support to uvc driver for NOMMU arch including add function uvc_queue_get_unmapped_area() and make some changes in uvc_queue_mmap(). So that uvc camera can be used on nommu arch like blackfin. Signed-off-by: Bob Liu <lliubbo@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/uvc/uvc_queue.c34
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c17
-rw-r--r--drivers/media/video/uvc/uvcvideo.h4
3 files changed, 54 insertions, 1 deletions
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index f14581bd707f..109a06384a8f 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -424,7 +424,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
424 break; 424 break;
425 } 425 }
426 426
427 if (i == queue->count || size != queue->buf_size) { 427 if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) {
428 ret = -EINVAL; 428 ret = -EINVAL;
429 goto done; 429 goto done;
430 } 430 }
@@ -436,6 +436,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
436 vma->vm_flags |= VM_IO; 436 vma->vm_flags |= VM_IO;
437 437
438 addr = (unsigned long)queue->mem + buffer->buf.m.offset; 438 addr = (unsigned long)queue->mem + buffer->buf.m.offset;
439#ifdef CONFIG_MMU
439 while (size > 0) { 440 while (size > 0) {
440 page = vmalloc_to_page((void *)addr); 441 page = vmalloc_to_page((void *)addr);
441 if ((ret = vm_insert_page(vma, start, page)) < 0) 442 if ((ret = vm_insert_page(vma, start, page)) < 0)
@@ -445,6 +446,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
445 addr += PAGE_SIZE; 446 addr += PAGE_SIZE;
446 size -= PAGE_SIZE; 447 size -= PAGE_SIZE;
447 } 448 }
449#endif
448 450
449 vma->vm_ops = &uvc_vm_ops; 451 vma->vm_ops = &uvc_vm_ops;
450 vma->vm_private_data = buffer; 452 vma->vm_private_data = buffer;
@@ -488,6 +490,36 @@ done:
488 return mask; 490 return mask;
489} 491}
490 492
493#ifndef CONFIG_MMU
494/*
495 * Get unmapped area.
496 *
497 * NO-MMU arch need this function to make mmap() work correctly.
498 */
499unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
500 unsigned long pgoff)
501{
502 struct uvc_buffer *buffer;
503 unsigned int i;
504 unsigned long ret;
505
506 mutex_lock(&queue->mutex);
507 for (i = 0; i < queue->count; ++i) {
508 buffer = &queue->buffer[i];
509 if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff)
510 break;
511 }
512 if (i == queue->count) {
513 ret = -EINVAL;
514 goto done;
515 }
516 ret = (unsigned long)queue->mem + buffer->buf.m.offset;
517done:
518 mutex_unlock(&queue->mutex);
519 return ret;
520}
521#endif
522
491/* 523/*
492 * Enable or disable the video buffers queue. 524 * Enable or disable the video buffers queue.
493 * 525 *
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 6e8aad44c4bd..543a80395b7f 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -1114,6 +1114,20 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
1114 return uvc_queue_poll(&stream->queue, file, wait); 1114 return uvc_queue_poll(&stream->queue, file, wait);
1115} 1115}
1116 1116
1117#ifndef CONFIG_MMU
1118static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
1119 unsigned long addr, unsigned long len, unsigned long pgoff,
1120 unsigned long flags)
1121{
1122 struct uvc_fh *handle = file->private_data;
1123 struct uvc_streaming *stream = handle->stream;
1124
1125 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n");
1126
1127 return uvc_queue_get_unmapped_area(&stream->queue, pgoff);
1128}
1129#endif
1130
1117const struct v4l2_file_operations uvc_fops = { 1131const struct v4l2_file_operations uvc_fops = {
1118 .owner = THIS_MODULE, 1132 .owner = THIS_MODULE,
1119 .open = uvc_v4l2_open, 1133 .open = uvc_v4l2_open,
@@ -1122,5 +1136,8 @@ const struct v4l2_file_operations uvc_fops = {
1122 .read = uvc_v4l2_read, 1136 .read = uvc_v4l2_read,
1123 .mmap = uvc_v4l2_mmap, 1137 .mmap = uvc_v4l2_mmap,
1124 .poll = uvc_v4l2_poll, 1138 .poll = uvc_v4l2_poll,
1139#ifndef CONFIG_MMU
1140 .get_unmapped_area = uvc_v4l2_get_unmapped_area,
1141#endif
1125}; 1142};
1126 1143
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 38dd4e18a2ca..0275613c5f33 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -600,6 +600,10 @@ extern int uvc_queue_mmap(struct uvc_video_queue *queue,
600 struct vm_area_struct *vma); 600 struct vm_area_struct *vma);
601extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, 601extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
602 struct file *file, poll_table *wait); 602 struct file *file, poll_table *wait);
603#ifndef CONFIG_MMU
604extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
605 unsigned long pgoff);
606#endif
603extern int uvc_queue_allocated(struct uvc_video_queue *queue); 607extern int uvc_queue_allocated(struct uvc_video_queue *queue);
604static inline int uvc_queue_streaming(struct uvc_video_queue *queue) 608static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
605{ 609{