diff options
author | Jonathan Corbet <corbet@lwn.net> | 2011-06-20 15:14:40 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:53:11 -0400 |
commit | a9b36e850782db853b9da050be9ed2050de51ad4 (patch) | |
tree | 40f372b8a9e6ad06eca64cc0f199e4edfa7b461a | |
parent | 6c895d548c393d913152195c9e70816e13c64f9f (diff) |
[media] marvell-cam: implement contiguous DMA operation
The core driver can now operate in either vmalloc or dma-contig modes;
obviously the latter is preferable when it is supported. Default is
currently vmalloc on all platforms; load the module with buffer_mode=1 for
contiguous DMA mode.
Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/marvell-ccic/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/cafe-driver.c | 6 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/mcam-core.c | 230 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/mcam-core.h | 21 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/mmp-driver.c | 1 |
5 files changed, 205 insertions, 54 deletions
diff --git a/drivers/media/video/marvell-ccic/Kconfig b/drivers/media/video/marvell-ccic/Kconfig index eb535b10000c..22314a0fa23b 100644 --- a/drivers/media/video/marvell-ccic/Kconfig +++ b/drivers/media/video/marvell-ccic/Kconfig | |||
@@ -14,6 +14,7 @@ config VIDEO_MMP_CAMERA | |||
14 | select VIDEO_OV7670 | 14 | select VIDEO_OV7670 |
15 | select I2C_GPIO | 15 | select I2C_GPIO |
16 | select VIDEOBUF2_VMALLOC | 16 | select VIDEOBUF2_VMALLOC |
17 | select VIDEOBUF2_DMA_CONTIG | ||
17 | ---help--- | 18 | ---help--- |
18 | This is a Video4Linux2 driver for the integrated camera | 19 | This is a Video4Linux2 driver for the integrated camera |
19 | controller found on Marvell Armada 610 application | 20 | controller found on Marvell Armada 610 application |
diff --git a/drivers/media/video/marvell-ccic/cafe-driver.c b/drivers/media/video/marvell-ccic/cafe-driver.c index 6a29cc1c45a5..d030f9beae88 100644 --- a/drivers/media/video/marvell-ccic/cafe-driver.c +++ b/drivers/media/video/marvell-ccic/cafe-driver.c | |||
@@ -482,6 +482,12 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
482 | mcam->clock_speed = 45; | 482 | mcam->clock_speed = 45; |
483 | mcam->use_smbus = 1; | 483 | mcam->use_smbus = 1; |
484 | /* | 484 | /* |
485 | * Vmalloc mode for buffers is traditional with this driver. | ||
486 | * We *might* be able to run DMA_contig, especially on a system | ||
487 | * with CMA in it. | ||
488 | */ | ||
489 | mcam->buffer_mode = B_vmalloc; | ||
490 | /* | ||
485 | * Get set up on the PCI bus. | 491 | * Get set up on the PCI bus. |
486 | */ | 492 | */ |
487 | ret = pci_enable_device(pdev); | 493 | ret = pci_enable_device(pdev); |
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c index ca3c56f05f0d..419b4e5f6988 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.c +++ b/drivers/media/video/marvell-ccic/mcam-core.c | |||
@@ -25,9 +25,16 @@ | |||
25 | #include <media/v4l2-chip-ident.h> | 25 | #include <media/v4l2-chip-ident.h> |
26 | #include <media/ov7670.h> | 26 | #include <media/ov7670.h> |
27 | #include <media/videobuf2-vmalloc.h> | 27 | #include <media/videobuf2-vmalloc.h> |
28 | #include <media/videobuf2-dma-contig.h> | ||
28 | 29 | ||
29 | #include "mcam-core.h" | 30 | #include "mcam-core.h" |
30 | 31 | ||
32 | /* | ||
33 | * Basic frame stats - to be deleted shortly | ||
34 | */ | ||
35 | static int frames; | ||
36 | static int singles; | ||
37 | static int delivered; | ||
31 | 38 | ||
32 | /* | 39 | /* |
33 | * Internal DMA buffer management. Since the controller cannot do S/G I/O, | 40 | * Internal DMA buffer management. Since the controller cannot do S/G I/O, |
@@ -48,7 +55,8 @@ MODULE_PARM_DESC(alloc_bufs_at_read, | |||
48 | "Non-zero value causes DMA buffers to be allocated when the " | 55 | "Non-zero value causes DMA buffers to be allocated when the " |
49 | "video capture device is read, rather than at module load " | 56 | "video capture device is read, rather than at module load " |
50 | "time. This saves memory, but decreases the chances of " | 57 | "time. This saves memory, but decreases the chances of " |
51 | "successfully getting those buffers."); | 58 | "successfully getting those buffers. This parameter is " |
59 | "only used in the vmalloc buffer mode"); | ||
52 | 60 | ||
53 | static int n_dma_bufs = 3; | 61 | static int n_dma_bufs = 3; |
54 | module_param(n_dma_bufs, uint, 0644); | 62 | module_param(n_dma_bufs, uint, 0644); |
@@ -82,6 +90,13 @@ MODULE_PARM_DESC(flip, | |||
82 | "If set, the sensor will be instructed to flip the image " | 90 | "If set, the sensor will be instructed to flip the image " |
83 | "vertically."); | 91 | "vertically."); |
84 | 92 | ||
93 | static int buffer_mode = -1; | ||
94 | module_param(buffer_mode, int, 0444); | ||
95 | MODULE_PARM_DESC(buffer_mode, | ||
96 | "Set the buffer mode to be used; default is to go with what " | ||
97 | "the platform driver asks for. Set to 0 for vmalloc, 1 for " | ||
98 | "DMA contiguous."); | ||
99 | |||
85 | /* | 100 | /* |
86 | * Status flags. Always manipulated with bit operations. | 101 | * Status flags. Always manipulated with bit operations. |
87 | */ | 102 | */ |
@@ -90,6 +105,7 @@ MODULE_PARM_DESC(flip, | |||
90 | #define CF_BUF2_VALID 2 | 105 | #define CF_BUF2_VALID 2 |
91 | #define CF_DMA_ACTIVE 3 /* A frame is incoming */ | 106 | #define CF_DMA_ACTIVE 3 /* A frame is incoming */ |
92 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ | 107 | #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ |
108 | #define CF_SINGLE_BUFFER 5 /* Running with a single buffer */ | ||
93 | 109 | ||
94 | #define sensor_call(cam, o, f, args...) \ | 110 | #define sensor_call(cam, o, f, args...) \ |
95 | v4l2_subdev_call(cam->sensor, o, f, ##args) | 111 | v4l2_subdev_call(cam->sensor, o, f, ##args) |
@@ -197,10 +213,9 @@ static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) | |||
197 | */ | 213 | */ |
198 | 214 | ||
199 | /* | 215 | /* |
200 | * Do everything we think we need to have the interface operating | 216 | * Set up DMA buffers when operating in vmalloc mode |
201 | * according to the desired format. | ||
202 | */ | 217 | */ |
203 | static void mcam_ctlr_dma(struct mcam_camera *cam) | 218 | static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) |
204 | { | 219 | { |
205 | /* | 220 | /* |
206 | * Store the first two Y buffers (we aren't supporting | 221 | * Store the first two Y buffers (we aren't supporting |
@@ -219,6 +234,57 @@ static void mcam_ctlr_dma(struct mcam_camera *cam) | |||
219 | mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */ | 234 | mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */ |
220 | } | 235 | } |
221 | 236 | ||
237 | /* | ||
238 | * Set up a contiguous buffer for the given frame. Here also is where | ||
239 | * the underrun strategy is set: if there is no buffer available, reuse | ||
240 | * the buffer from the other BAR and set the CF_SINGLE_BUFFER flag to | ||
241 | * keep the interrupt handler from giving that buffer back to user | ||
242 | * space. In this way, we always have a buffer to DMA to and don't | ||
243 | * have to try to play games stopping and restarting the controller. | ||
244 | */ | ||
245 | static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) | ||
246 | { | ||
247 | struct mcam_vb_buffer *buf; | ||
248 | /* | ||
249 | * If there are no available buffers, go into single mode | ||
250 | */ | ||
251 | if (list_empty(&cam->buffers)) { | ||
252 | buf = cam->vb_bufs[frame ^ 0x1]; | ||
253 | cam->vb_bufs[frame] = buf; | ||
254 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, | ||
255 | vb2_dma_contig_plane_paddr(&buf->vb_buf, 0)); | ||
256 | set_bit(CF_SINGLE_BUFFER, &cam->flags); | ||
257 | singles++; | ||
258 | return; | ||
259 | } | ||
260 | /* | ||
261 | * OK, we have a buffer we can use. | ||
262 | */ | ||
263 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); | ||
264 | list_del_init(&buf->queue); | ||
265 | mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, | ||
266 | vb2_dma_contig_plane_paddr(&buf->vb_buf, 0)); | ||
267 | cam->vb_bufs[frame] = buf; | ||
268 | clear_bit(CF_SINGLE_BUFFER, &cam->flags); | ||
269 | } | ||
270 | |||
271 | static void mcam_ctlr_dma_contig(struct mcam_camera *cam) | ||
272 | { | ||
273 | mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); | ||
274 | cam->nbufs = 2; | ||
275 | mcam_set_contig_buffer(cam, 0); | ||
276 | mcam_set_contig_buffer(cam, 1); | ||
277 | } | ||
278 | |||
279 | |||
280 | static void mcam_ctlr_dma(struct mcam_camera *cam) | ||
281 | { | ||
282 | if (cam->buffer_mode == B_DMA_contig) | ||
283 | mcam_ctlr_dma_contig(cam); | ||
284 | else | ||
285 | mcam_ctlr_dma_vmalloc(cam); | ||
286 | } | ||
287 | |||
222 | static void mcam_ctlr_image(struct mcam_camera *cam) | 288 | static void mcam_ctlr_image(struct mcam_camera *cam) |
223 | { | 289 | { |
224 | int imgsz; | 290 | int imgsz; |
@@ -542,7 +608,7 @@ static void mcam_free_dma_bufs(struct mcam_camera *cam) | |||
542 | /* | 608 | /* |
543 | * Get everything ready, and start grabbing frames. | 609 | * Get everything ready, and start grabbing frames. |
544 | */ | 610 | */ |
545 | static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state) | 611 | static int mcam_read_setup(struct mcam_camera *cam) |
546 | { | 612 | { |
547 | int ret; | 613 | int ret; |
548 | unsigned long flags; | 614 | unsigned long flags; |
@@ -551,9 +617,9 @@ static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state) | |||
551 | * Configuration. If we still don't have DMA buffers, | 617 | * Configuration. If we still don't have DMA buffers, |
552 | * make one last, desperate attempt. | 618 | * make one last, desperate attempt. |
553 | */ | 619 | */ |
554 | if (cam->nbufs == 0) | 620 | if (cam->buffer_mode == B_vmalloc && cam->nbufs == 0 && |
555 | if (mcam_alloc_dma_bufs(cam, 0)) | 621 | mcam_alloc_dma_bufs(cam, 0)) |
556 | return -ENOMEM; | 622 | return -ENOMEM; |
557 | 623 | ||
558 | if (mcam_needs_config(cam)) { | 624 | if (mcam_needs_config(cam)) { |
559 | mcam_cam_configure(cam); | 625 | mcam_cam_configure(cam); |
@@ -568,7 +634,7 @@ static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state) | |||
568 | spin_lock_irqsave(&cam->dev_lock, flags); | 634 | spin_lock_irqsave(&cam->dev_lock, flags); |
569 | mcam_reset_buffers(cam); | 635 | mcam_reset_buffers(cam); |
570 | mcam_ctlr_irq_enable(cam); | 636 | mcam_ctlr_irq_enable(cam); |
571 | cam->state = state; | 637 | cam->state = S_STREAMING; |
572 | mcam_ctlr_start(cam); | 638 | mcam_ctlr_start(cam); |
573 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 639 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
574 | return 0; | 640 | return 0; |
@@ -587,8 +653,10 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, | |||
587 | 653 | ||
588 | sizes[0] = cam->pix_format.sizeimage; | 654 | sizes[0] = cam->pix_format.sizeimage; |
589 | *num_planes = 1; /* Someday we have to support planar formats... */ | 655 | *num_planes = 1; /* Someday we have to support planar formats... */ |
590 | if (*nbufs < 2 || *nbufs > 32) | 656 | if (*nbufs < 3 || *nbufs > 32) |
591 | *nbufs = 6; /* semi-arbitrary numbers */ | 657 | *nbufs = 3; /* semi-arbitrary numbers */ |
658 | if (cam->buffer_mode == B_DMA_contig) | ||
659 | alloc_ctxs[0] = cam->vb_alloc_ctx; | ||
592 | return 0; | 660 | return 0; |
593 | } | 661 | } |
594 | 662 | ||
@@ -605,10 +673,14 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb) | |||
605 | struct mcam_vb_buffer *mvb = vb_to_mvb(vb); | 673 | struct mcam_vb_buffer *mvb = vb_to_mvb(vb); |
606 | struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); | 674 | struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); |
607 | unsigned long flags; | 675 | unsigned long flags; |
676 | int start; | ||
608 | 677 | ||
609 | spin_lock_irqsave(&cam->dev_lock, flags); | 678 | spin_lock_irqsave(&cam->dev_lock, flags); |
610 | list_add(&cam->buffers, &mvb->queue); | 679 | start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers); |
680 | list_add(&mvb->queue, &cam->buffers); | ||
611 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 681 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
682 | if (start) | ||
683 | mcam_read_setup(cam); | ||
612 | } | 684 | } |
613 | 685 | ||
614 | /* | 686 | /* |
@@ -636,13 +708,22 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq) | |||
636 | static int mcam_vb_start_streaming(struct vb2_queue *vq) | 708 | static int mcam_vb_start_streaming(struct vb2_queue *vq) |
637 | { | 709 | { |
638 | struct mcam_camera *cam = vb2_get_drv_priv(vq); | 710 | struct mcam_camera *cam = vb2_get_drv_priv(vq); |
639 | int ret = -EINVAL; | ||
640 | 711 | ||
641 | if (cam->state == S_IDLE) { | 712 | if (cam->state != S_IDLE) |
642 | cam->sequence = 0; | 713 | return -EINVAL; |
643 | ret = mcam_read_setup(cam, S_STREAMING); | 714 | cam->sequence = 0; |
715 | /* | ||
716 | * Videobuf2 sneakily hoards all the buffers and won't | ||
717 | * give them to us until *after* streaming starts. But | ||
718 | * we can't actually start streaming until we have a | ||
719 | * destination. So go into a wait state and hope they | ||
720 | * give us buffers soon. | ||
721 | */ | ||
722 | if (cam->buffer_mode != B_vmalloc && list_empty(&cam->buffers)) { | ||
723 | cam->state = S_BUFWAIT; | ||
724 | return 0; | ||
644 | } | 725 | } |
645 | return ret; | 726 | return mcam_read_setup(cam); |
646 | } | 727 | } |
647 | 728 | ||
648 | static int mcam_vb_stop_streaming(struct vb2_queue *vq) | 729 | static int mcam_vb_stop_streaming(struct vb2_queue *vq) |
@@ -650,6 +731,11 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq) | |||
650 | struct mcam_camera *cam = vb2_get_drv_priv(vq); | 731 | struct mcam_camera *cam = vb2_get_drv_priv(vq); |
651 | unsigned long flags; | 732 | unsigned long flags; |
652 | 733 | ||
734 | if (cam->state == S_BUFWAIT) { | ||
735 | /* They never gave us buffers */ | ||
736 | cam->state = S_IDLE; | ||
737 | return 0; | ||
738 | } | ||
653 | if (cam->state != S_STREAMING) | 739 | if (cam->state != S_STREAMING) |
654 | return -EINVAL; | 740 | return -EINVAL; |
655 | mcam_ctlr_stop_dma(cam); | 741 | mcam_ctlr_stop_dma(cam); |
@@ -683,7 +769,11 @@ static int mcam_setup_vb2(struct mcam_camera *cam) | |||
683 | vq->io_modes = VB2_MMAP; /* Add userptr */ | 769 | vq->io_modes = VB2_MMAP; /* Add userptr */ |
684 | vq->drv_priv = cam; | 770 | vq->drv_priv = cam; |
685 | vq->ops = &mcam_vb2_ops; | 771 | vq->ops = &mcam_vb2_ops; |
686 | vq->mem_ops = &vb2_vmalloc_memops; | 772 | if (cam->buffer_mode == B_DMA_contig) { |
773 | vq->mem_ops = &vb2_dma_contig_memops; | ||
774 | cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); | ||
775 | } else | ||
776 | vq->mem_ops = &vb2_vmalloc_memops; | ||
687 | vq->buf_struct_size = sizeof(struct mcam_vb_buffer); | 777 | vq->buf_struct_size = sizeof(struct mcam_vb_buffer); |
688 | 778 | ||
689 | return vb2_queue_init(vq); | 779 | return vb2_queue_init(vq); |
@@ -692,6 +782,8 @@ static int mcam_setup_vb2(struct mcam_camera *cam) | |||
692 | static void mcam_cleanup_vb2(struct mcam_camera *cam) | 782 | static void mcam_cleanup_vb2(struct mcam_camera *cam) |
693 | { | 783 | { |
694 | vb2_queue_release(&cam->vb_queue); | 784 | vb2_queue_release(&cam->vb_queue); |
785 | if (cam->buffer_mode == B_DMA_contig) | ||
786 | vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx); | ||
695 | } | 787 | } |
696 | 788 | ||
697 | static ssize_t mcam_v4l_read(struct file *filp, | 789 | static ssize_t mcam_v4l_read(struct file *filp, |
@@ -809,6 +901,7 @@ static int mcam_v4l_open(struct file *filp) | |||
809 | 901 | ||
810 | filp->private_data = cam; | 902 | filp->private_data = cam; |
811 | 903 | ||
904 | frames = singles = delivered = 0; | ||
812 | mutex_lock(&cam->s_mutex); | 905 | mutex_lock(&cam->s_mutex); |
813 | if (cam->users == 0) { | 906 | if (cam->users == 0) { |
814 | ret = mcam_setup_vb2(cam); | 907 | ret = mcam_setup_vb2(cam); |
@@ -829,6 +922,8 @@ static int mcam_v4l_release(struct file *filp) | |||
829 | { | 922 | { |
830 | struct mcam_camera *cam = filp->private_data; | 923 | struct mcam_camera *cam = filp->private_data; |
831 | 924 | ||
925 | cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames, | ||
926 | singles, delivered); | ||
832 | mutex_lock(&cam->s_mutex); | 927 | mutex_lock(&cam->s_mutex); |
833 | (cam->users)--; | 928 | (cam->users)--; |
834 | if (filp == cam->owner) { | 929 | if (filp == cam->owner) { |
@@ -838,7 +933,7 @@ static int mcam_v4l_release(struct file *filp) | |||
838 | if (cam->users == 0) { | 933 | if (cam->users == 0) { |
839 | mcam_cleanup_vb2(cam); | 934 | mcam_cleanup_vb2(cam); |
840 | mcam_ctlr_power_down(cam); | 935 | mcam_ctlr_power_down(cam); |
841 | if (alloc_bufs_at_read) | 936 | if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) |
842 | mcam_free_dma_bufs(cam); | 937 | mcam_free_dma_bufs(cam); |
843 | } | 938 | } |
844 | mutex_unlock(&cam->s_mutex); | 939 | mutex_unlock(&cam->s_mutex); |
@@ -993,18 +1088,17 @@ static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv, | |||
993 | * Make sure we have appropriate DMA buffers. | 1088 | * Make sure we have appropriate DMA buffers. |
994 | */ | 1089 | */ |
995 | ret = -ENOMEM; | 1090 | ret = -ENOMEM; |
996 | if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage) | 1091 | if (cam->buffer_mode == B_vmalloc) { |
997 | mcam_free_dma_bufs(cam); | 1092 | if (cam->nbufs > 0 && |
998 | if (cam->nbufs == 0) { | 1093 | cam->dma_buf_size < cam->pix_format.sizeimage) |
999 | if (mcam_alloc_dma_bufs(cam, 0)) | 1094 | mcam_free_dma_bufs(cam); |
1000 | goto out; | 1095 | if (cam->nbufs == 0) { |
1096 | if (mcam_alloc_dma_bufs(cam, 0)) | ||
1097 | goto out; | ||
1098 | } | ||
1001 | } | 1099 | } |
1002 | /* | 1100 | mcam_set_config_needed(cam, 1); |
1003 | * It looks like this might work, so let's program the sensor. | 1101 | ret = 0; |
1004 | */ | ||
1005 | ret = mcam_cam_configure(cam); | ||
1006 | if (!ret) | ||
1007 | ret = mcam_ctlr_configure(cam); | ||
1008 | out: | 1102 | out: |
1009 | mutex_unlock(&cam->s_mutex); | 1103 | mutex_unlock(&cam->s_mutex); |
1010 | return ret; | 1104 | return ret; |
@@ -1214,7 +1308,20 @@ static struct video_device mcam_v4l_template = { | |||
1214 | */ | 1308 | */ |
1215 | 1309 | ||
1216 | 1310 | ||
1311 | static void mcam_buffer_done(struct mcam_camera *cam, int frame, | ||
1312 | struct vb2_buffer *vbuf) | ||
1313 | { | ||
1314 | vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage; | ||
1315 | vbuf->v4l2_buf.sequence = cam->buf_seq[frame]; | ||
1316 | vbuf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
1317 | vbuf->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; | ||
1318 | vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage); | ||
1319 | vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE); | ||
1320 | } | ||
1217 | 1321 | ||
1322 | /* | ||
1323 | * Copy data out to user space in the vmalloc case | ||
1324 | */ | ||
1218 | static void mcam_frame_tasklet(unsigned long data) | 1325 | static void mcam_frame_tasklet(unsigned long data) |
1219 | { | 1326 | { |
1220 | struct mcam_camera *cam = (struct mcam_camera *) data; | 1327 | struct mcam_camera *cam = (struct mcam_camera *) data; |
@@ -1232,8 +1339,11 @@ static void mcam_frame_tasklet(unsigned long data) | |||
1232 | cam->next_buf = 0; | 1339 | cam->next_buf = 0; |
1233 | if (!test_bit(bufno, &cam->flags)) | 1340 | if (!test_bit(bufno, &cam->flags)) |
1234 | continue; | 1341 | continue; |
1235 | if (list_empty(&cam->buffers)) | 1342 | if (list_empty(&cam->buffers)) { |
1343 | singles++; | ||
1236 | break; /* Leave it valid, hope for better later */ | 1344 | break; /* Leave it valid, hope for better later */ |
1345 | } | ||
1346 | delivered++; | ||
1237 | clear_bit(bufno, &cam->flags); | 1347 | clear_bit(bufno, &cam->flags); |
1238 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, | 1348 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, |
1239 | queue); | 1349 | queue); |
@@ -1244,18 +1354,25 @@ static void mcam_frame_tasklet(unsigned long data) | |||
1244 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 1354 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
1245 | memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno], | 1355 | memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno], |
1246 | cam->pix_format.sizeimage); | 1356 | cam->pix_format.sizeimage); |
1247 | buf->vb_buf.v4l2_buf.bytesused = cam->pix_format.sizeimage; | 1357 | mcam_buffer_done(cam, bufno, &buf->vb_buf); |
1248 | buf->vb_buf.v4l2_buf.sequence = cam->buf_seq[bufno]; | ||
1249 | buf->vb_buf.v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
1250 | buf->vb_buf.v4l2_buf.flags |= V4L2_BUF_FLAG_DONE; | ||
1251 | vb2_set_plane_payload(&buf->vb_buf, 0, | ||
1252 | cam->pix_format.sizeimage); | ||
1253 | vb2_buffer_done(&buf->vb_buf, VB2_BUF_STATE_DONE); | ||
1254 | spin_lock_irqsave(&cam->dev_lock, flags); | 1358 | spin_lock_irqsave(&cam->dev_lock, flags); |
1255 | } | 1359 | } |
1256 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 1360 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
1257 | } | 1361 | } |
1258 | 1362 | ||
1363 | /* | ||
1364 | * For direct DMA, mark the buffer ready and set up another one. | ||
1365 | */ | ||
1366 | static void mcam_dma_complete(struct mcam_camera *cam, int frame) | ||
1367 | { | ||
1368 | struct mcam_vb_buffer *buf = cam->vb_bufs[frame]; | ||
1369 | |||
1370 | if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) { | ||
1371 | delivered++; | ||
1372 | mcam_buffer_done(cam, frame, &buf->vb_buf); | ||
1373 | } | ||
1374 | mcam_set_contig_buffer(cam, frame); | ||
1375 | } | ||
1259 | 1376 | ||
1260 | 1377 | ||
1261 | static void mcam_frame_complete(struct mcam_camera *cam, int frame) | 1378 | static void mcam_frame_complete(struct mcam_camera *cam, int frame) |
@@ -1265,21 +1382,20 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame) | |||
1265 | */ | 1382 | */ |
1266 | set_bit(frame, &cam->flags); | 1383 | set_bit(frame, &cam->flags); |
1267 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | 1384 | clear_bit(CF_DMA_ACTIVE, &cam->flags); |
1268 | if (cam->next_buf < 0) | 1385 | cam->next_buf = frame; |
1269 | cam->next_buf = frame; | ||
1270 | cam->buf_seq[frame] = ++(cam->sequence); | 1386 | cam->buf_seq[frame] = ++(cam->sequence); |
1387 | cam->last_delivered = frame; | ||
1271 | 1388 | ||
1389 | frames++; | ||
1272 | switch (cam->state) { | 1390 | switch (cam->state) { |
1273 | /* | 1391 | /* |
1274 | * For the streaming case, we defer the real work to the | 1392 | * We're streaming and have a ready frame, hand it back |
1275 | * camera tasklet. | ||
1276 | * | ||
1277 | * FIXME: if the application is not consuming the buffers, | ||
1278 | * we should eventually put things on hold and restart in | ||
1279 | * vidioc_dqbuf(). | ||
1280 | */ | 1393 | */ |
1281 | case S_STREAMING: | 1394 | case S_STREAMING: |
1282 | tasklet_schedule(&cam->s_tasklet); | 1395 | if (cam->buffer_mode == B_vmalloc) |
1396 | tasklet_schedule(&cam->s_tasklet); | ||
1397 | else | ||
1398 | mcam_dma_complete(cam, frame); | ||
1283 | break; | 1399 | break; |
1284 | 1400 | ||
1285 | default: | 1401 | default: |
@@ -1356,7 +1472,18 @@ int mccic_register(struct mcam_camera *cam) | |||
1356 | INIT_LIST_HEAD(&cam->dev_list); | 1472 | INIT_LIST_HEAD(&cam->dev_list); |
1357 | INIT_LIST_HEAD(&cam->buffers); | 1473 | INIT_LIST_HEAD(&cam->buffers); |
1358 | tasklet_init(&cam->s_tasklet, mcam_frame_tasklet, (unsigned long) cam); | 1474 | tasklet_init(&cam->s_tasklet, mcam_frame_tasklet, (unsigned long) cam); |
1359 | 1475 | /* | |
1476 | * User space may want to override the asked-for buffer mode; | ||
1477 | * here's hoping they know what they're doing. | ||
1478 | */ | ||
1479 | if (buffer_mode == 0) | ||
1480 | cam->buffer_mode = B_vmalloc; | ||
1481 | else if (buffer_mode == 1) | ||
1482 | cam->buffer_mode = B_DMA_contig; | ||
1483 | else if (buffer_mode != -1) | ||
1484 | printk(KERN_ERR "marvel-cam: " | ||
1485 | "Strange module buffer mode %d - ignoring\n", | ||
1486 | buffer_mode); | ||
1360 | mcam_ctlr_init(cam); | 1487 | mcam_ctlr_init(cam); |
1361 | 1488 | ||
1362 | /* | 1489 | /* |
@@ -1390,7 +1517,7 @@ int mccic_register(struct mcam_camera *cam) | |||
1390 | /* | 1517 | /* |
1391 | * If so requested, try to get our DMA buffers now. | 1518 | * If so requested, try to get our DMA buffers now. |
1392 | */ | 1519 | */ |
1393 | if (!alloc_bufs_at_read) { | 1520 | if (cam->buffer_mode == B_vmalloc && !alloc_bufs_at_read) { |
1394 | if (mcam_alloc_dma_bufs(cam, 1)) | 1521 | if (mcam_alloc_dma_bufs(cam, 1)) |
1395 | cam_warn(cam, "Unable to alloc DMA buffers at load" | 1522 | cam_warn(cam, "Unable to alloc DMA buffers at load" |
1396 | " will try again later."); | 1523 | " will try again later."); |
@@ -1418,7 +1545,8 @@ void mccic_shutdown(struct mcam_camera *cam) | |||
1418 | mcam_ctlr_power_down(cam); | 1545 | mcam_ctlr_power_down(cam); |
1419 | } | 1546 | } |
1420 | vb2_queue_release(&cam->vb_queue); | 1547 | vb2_queue_release(&cam->vb_queue); |
1421 | mcam_free_dma_bufs(cam); | 1548 | if (cam->buffer_mode == B_vmalloc) |
1549 | mcam_free_dma_bufs(cam); | ||
1422 | video_unregister_device(&cam->vdev); | 1550 | video_unregister_device(&cam->vdev); |
1423 | v4l2_device_unregister(&cam->v4l2_dev); | 1551 | v4l2_device_unregister(&cam->v4l2_dev); |
1424 | } | 1552 | } |
@@ -1452,7 +1580,7 @@ int mccic_resume(struct mcam_camera *cam) | |||
1452 | 1580 | ||
1453 | set_bit(CF_CONFIG_NEEDED, &cam->flags); | 1581 | set_bit(CF_CONFIG_NEEDED, &cam->flags); |
1454 | if (cam->state == S_STREAMING) | 1582 | if (cam->state == S_STREAMING) |
1455 | ret = mcam_read_setup(cam, cam->state); | 1583 | ret = mcam_read_setup(cam); |
1456 | return ret; | 1584 | return ret; |
1457 | } | 1585 | } |
1458 | #endif /* CONFIG_PM */ | 1586 | #endif /* CONFIG_PM */ |
diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index f40450cf72a0..2e667a05620a 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h | |||
@@ -27,11 +27,21 @@ enum mcam_state { | |||
27 | S_NOTREADY, /* Not yet initialized */ | 27 | S_NOTREADY, /* Not yet initialized */ |
28 | S_IDLE, /* Just hanging around */ | 28 | S_IDLE, /* Just hanging around */ |
29 | S_FLAKED, /* Some sort of problem */ | 29 | S_FLAKED, /* Some sort of problem */ |
30 | S_STREAMING /* Streaming data */ | 30 | S_STREAMING, /* Streaming data */ |
31 | S_BUFWAIT /* streaming requested but no buffers yet */ | ||
31 | }; | 32 | }; |
32 | #define MAX_DMA_BUFS 3 | 33 | #define MAX_DMA_BUFS 3 |
33 | 34 | ||
34 | /* | 35 | /* |
36 | * Different platforms work best with different buffer modes, so we | ||
37 | * let the platform pick. | ||
38 | */ | ||
39 | enum mcam_buffer_mode { | ||
40 | B_vmalloc = 0, | ||
41 | B_DMA_contig | ||
42 | }; | ||
43 | |||
44 | /* | ||
35 | * A description of one of our devices. | 45 | * A description of one of our devices. |
36 | * Locking: controlled by s_mutex. Certain fields, however, require | 46 | * Locking: controlled by s_mutex. Certain fields, however, require |
37 | * the dev_lock spinlock; they are marked as such by comments. | 47 | * the dev_lock spinlock; they are marked as such by comments. |
@@ -49,7 +59,7 @@ struct mcam_camera { | |||
49 | unsigned int chip_id; | 59 | unsigned int chip_id; |
50 | short int clock_speed; /* Sensor clock speed, default 30 */ | 60 | short int clock_speed; /* Sensor clock speed, default 30 */ |
51 | short int use_smbus; /* SMBUS or straight I2c? */ | 61 | short int use_smbus; /* SMBUS or straight I2c? */ |
52 | 62 | enum mcam_buffer_mode buffer_mode; | |
53 | /* | 63 | /* |
54 | * Callbacks from the core to the platform code. | 64 | * Callbacks from the core to the platform code. |
55 | */ | 65 | */ |
@@ -79,7 +89,7 @@ struct mcam_camera { | |||
79 | struct vb2_queue vb_queue; | 89 | struct vb2_queue vb_queue; |
80 | struct list_head buffers; /* Available frames */ | 90 | struct list_head buffers; /* Available frames */ |
81 | 91 | ||
82 | /* DMA buffers */ | 92 | /* DMA buffers - vmalloc mode */ |
83 | unsigned int nbufs; /* How many are alloc'd */ | 93 | unsigned int nbufs; /* How many are alloc'd */ |
84 | int next_buf; /* Next to consume (dev_lock) */ | 94 | int next_buf; /* Next to consume (dev_lock) */ |
85 | unsigned int dma_buf_size; /* allocated size */ | 95 | unsigned int dma_buf_size; /* allocated size */ |
@@ -88,6 +98,11 @@ struct mcam_camera { | |||
88 | unsigned int sequence; /* Frame sequence number */ | 98 | unsigned int sequence; /* Frame sequence number */ |
89 | unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ | 99 | unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ |
90 | 100 | ||
101 | /* DMA buffers - contiguous DMA mode */ | ||
102 | struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS]; | ||
103 | struct vb2_alloc_ctx *vb_alloc_ctx; | ||
104 | unsigned short last_delivered; | ||
105 | |||
91 | struct tasklet_struct s_tasklet; | 106 | struct tasklet_struct s_tasklet; |
92 | 107 | ||
93 | /* Current operating parameters */ | 108 | /* Current operating parameters */ |
diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c index ac9976f23a61..7b9c48c897e5 100644 --- a/drivers/media/video/marvell-ccic/mmp-driver.c +++ b/drivers/media/video/marvell-ccic/mmp-driver.c | |||
@@ -180,6 +180,7 @@ static int mmpcam_probe(struct platform_device *pdev) | |||
180 | mcam->dev = &pdev->dev; | 180 | mcam->dev = &pdev->dev; |
181 | mcam->use_smbus = 0; | 181 | mcam->use_smbus = 0; |
182 | mcam->chip_id = V4L2_IDENT_ARMADA610; | 182 | mcam->chip_id = V4L2_IDENT_ARMADA610; |
183 | mcam->buffer_mode = B_vmalloc; /* Switch to dma */ | ||
183 | spin_lock_init(&mcam->dev_lock); | 184 | spin_lock_init(&mcam->dev_lock); |
184 | /* | 185 | /* |
185 | * Get our I/O memory. | 186 | * Get our I/O memory. |