aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorJonathan Corbet <corbet@lwn.net>2011-07-08 16:50:49 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:55:54 -0400
commit7498469f619e1ba380fc90042a2b1736c7c6942c (patch)
tree406d8a6efb7f5e772dbbc89fcc78afd5968601b7 /drivers/media
parent221a8248b9ca62a7304115782dca46a3f014f454 (diff)
[media] marvell-cam: Allow selection of supported buffer modes
The Marvell camera core can support all three videobuf2 buffer modes, which is slick, but it also requires that all three modes be built and present, even though only one is likely to be used. This patch allows the supported modes to be selected at configuration time, reducing the footprint of the driver. Prior to this patch, the MMP camera driver looked like this: mmp_camera 19092 0 videobuf2_core 15542 1 mmp_camera videobuf2_dma_sg 3173 1 mmp_camera videobuf2_dma_contig 2188 1 mmp_camera videobuf2_vmalloc 1718 1 mmp_camera videobuf2_memops 2100 3 videobuf2_dma_sg,videobuf2_dma_contig,videobuf2_vmalloc Afterward, instead, with scatter/gather only configured: mmp_camera 16021 0 videobuf2_core 15542 1 mmp_camera videobuf2_dma_sg 3173 1 mmp_camera videobuf2_memops 2100 1 videobuf2_dma_sg The total goes from 43,813 bytes to 36,836. The emphasis has been on simplicity and minimal #ifdef use rather than on squeezing out every possible byte of code. For configuration, the driver simply looks at which videobuf2 modes have been configured in and supports them all; it's simplistic but should be good enough. The cafe driver is set to support vmalloc and dma-contig; mmp supports only dma-sg, since that's the only mode that really makes sense to use. Signed-off-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/marvell-ccic/Kconfig3
-rw-r--r--drivers/media/video/marvell-ccic/mcam-core.c149
-rw-r--r--drivers/media/video/marvell-ccic/mcam-core.h59
3 files changed, 152 insertions, 59 deletions
diff --git a/drivers/media/video/marvell-ccic/Kconfig b/drivers/media/video/marvell-ccic/Kconfig
index 5be66e2e859..bf739e3b339 100644
--- a/drivers/media/video/marvell-ccic/Kconfig
+++ b/drivers/media/video/marvell-ccic/Kconfig
@@ -4,7 +4,6 @@ config VIDEO_CAFE_CCIC
4 select VIDEO_OV7670 4 select VIDEO_OV7670
5 select VIDEOBUF2_VMALLOC 5 select VIDEOBUF2_VMALLOC
6 select VIDEOBUF2_DMA_CONTIG 6 select VIDEOBUF2_DMA_CONTIG
7 select VIDEOBUF2_DMA_SG
8 ---help--- 7 ---help---
9 This is a video4linux2 driver for the Marvell 88ALP01 integrated 8 This is a video4linux2 driver for the Marvell 88ALP01 integrated
10 CMOS camera controller. This is the controller found on first- 9 CMOS camera controller. This is the controller found on first-
@@ -15,8 +14,6 @@ config VIDEO_MMP_CAMERA
15 depends on ARCH_MMP && I2C && VIDEO_V4L2 14 depends on ARCH_MMP && I2C && VIDEO_V4L2
16 select VIDEO_OV7670 15 select VIDEO_OV7670
17 select I2C_GPIO 16 select I2C_GPIO
18 select VIDEOBUF2_VMALLOC
19 select VIDEOBUF2_DMA_CONTIG
20 select VIDEOBUF2_DMA_SG 17 select VIDEOBUF2_DMA_SG
21 ---help--- 18 ---help---
22 This is a Video4Linux2 driver for the integrated camera 19 This is a Video4Linux2 driver for the integrated camera
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c
index 9867b3b5504..073e72c8f08 100644
--- a/drivers/media/video/marvell-ccic/mcam-core.c
+++ b/drivers/media/video/marvell-ccic/mcam-core.c
@@ -37,6 +37,7 @@ static int frames;
37static int singles; 37static int singles;
38static int delivered; 38static int delivered;
39 39
40#ifdef MCAM_MODE_VMALLOC
40/* 41/*
41 * Internal DMA buffer management. Since the controller cannot do S/G I/O, 42 * Internal DMA buffer management. Since the controller cannot do S/G I/O,
42 * we must have physically contiguous buffers to bring frames into. 43 * we must have physically contiguous buffers to bring frames into.
@@ -71,6 +72,10 @@ MODULE_PARM_DESC(dma_buf_size,
71 "The size of the allocated DMA buffers. If actual operating " 72 "The size of the allocated DMA buffers. If actual operating "
72 "parameters require larger buffers, an attempt to reallocate " 73 "parameters require larger buffers, an attempt to reallocate "
73 "will be made."); 74 "will be made.");
75#else /* MCAM_MODE_VMALLOC */
76static const int alloc_bufs_at_read = 0;
77static const int n_dma_bufs = 3; /* Used by S/G_PARM */
78#endif /* MCAM_MODE_VMALLOC */
74 79
75static int flip; 80static int flip;
76module_param(flip, bool, 0444); 81module_param(flip, bool, 0444);
@@ -256,6 +261,8 @@ static void mcam_ctlr_stop(struct mcam_camera *cam)
256} 261}
257 262
258/* ------------------------------------------------------------------- */ 263/* ------------------------------------------------------------------- */
264
265#ifdef MCAM_MODE_VMALLOC
259/* 266/*
260 * Code specific to the vmalloc buffer mode. 267 * Code specific to the vmalloc buffer mode.
261 */ 268 */
@@ -381,6 +388,46 @@ static void mcam_frame_tasklet(unsigned long data)
381} 388}
382 389
383 390
391/*
392 * Make sure our allocated buffers are up to the task.
393 */
394static int mcam_check_dma_buffers(struct mcam_camera *cam)
395{
396 if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage)
397 mcam_free_dma_bufs(cam);
398 if (cam->nbufs == 0)
399 return mcam_alloc_dma_bufs(cam, 0);
400 return 0;
401}
402
403static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
404{
405 tasklet_schedule(&cam->s_tasklet);
406}
407
408#else /* MCAM_MODE_VMALLOC */
409
410static inline int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
411{
412 return 0;
413}
414
415static inline void mcam_free_dma_bufs(struct mcam_camera *cam)
416{
417 return;
418}
419
420static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
421{
422 return 0;
423}
424
425
426
427#endif /* MCAM_MODE_VMALLOC */
428
429
430#ifdef MCAM_MODE_DMA_CONTIG
384/* ---------------------------------------------------------------------- */ 431/* ---------------------------------------------------------------------- */
385/* 432/*
386 * DMA-contiguous code. 433 * DMA-contiguous code.
@@ -444,8 +491,9 @@ static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
444 mcam_set_contig_buffer(cam, frame); 491 mcam_set_contig_buffer(cam, frame);
445} 492}
446 493
494#endif /* MCAM_MODE_DMA_CONTIG */
447 495
448 496#ifdef MCAM_MODE_DMA_SG
449/* ---------------------------------------------------------------------- */ 497/* ---------------------------------------------------------------------- */
450/* 498/*
451 * Scatter/gather-specific code. 499 * Scatter/gather-specific code.
@@ -540,6 +588,14 @@ static void mcam_sg_restart(struct mcam_camera *cam)
540 clear_bit(CF_SG_RESTART, &cam->flags); 588 clear_bit(CF_SG_RESTART, &cam->flags);
541} 589}
542 590
591#else /* MCAM_MODE_DMA_SG */
592
593static inline void mcam_sg_restart(struct mcam_camera *cam)
594{
595 return;
596}
597
598#endif /* MCAM_MODE_DMA_SG */
543 599
544/* ---------------------------------------------------------------------- */ 600/* ---------------------------------------------------------------------- */
545/* 601/*
@@ -605,17 +661,7 @@ static int mcam_ctlr_configure(struct mcam_camera *cam)
605 unsigned long flags; 661 unsigned long flags;
606 662
607 spin_lock_irqsave(&cam->dev_lock, flags); 663 spin_lock_irqsave(&cam->dev_lock, flags);
608 switch (cam->buffer_mode) { 664 cam->dma_setup(cam);
609 case B_vmalloc:
610 mcam_ctlr_dma_vmalloc(cam);
611 break;
612 case B_DMA_contig:
613 mcam_ctlr_dma_contig(cam);
614 break;
615 case B_DMA_sg:
616 mcam_ctlr_dma_sg(cam);
617 break;
618 }
619 mcam_ctlr_image(cam); 665 mcam_ctlr_image(cam);
620 mcam_set_config_needed(cam, 0); 666 mcam_set_config_needed(cam, 0);
621 clear_bit(CF_SG_RESTART, &cam->flags); 667 clear_bit(CF_SG_RESTART, &cam->flags);
@@ -948,6 +994,8 @@ static const struct vb2_ops mcam_vb2_ops = {
948 .wait_finish = mcam_vb_wait_finish, 994 .wait_finish = mcam_vb_wait_finish,
949}; 995};
950 996
997
998#ifdef MCAM_MODE_DMA_SG
951/* 999/*
952 * Scatter/gather mode uses all of the above functions plus a 1000 * Scatter/gather mode uses all of the above functions plus a
953 * few extras to deal with DMA mapping. 1001 * few extras to deal with DMA mapping.
@@ -1022,6 +1070,8 @@ static const struct vb2_ops mcam_vb2_sg_ops = {
1022 .wait_finish = mcam_vb_wait_finish, 1070 .wait_finish = mcam_vb_wait_finish,
1023}; 1071};
1024 1072
1073#endif /* MCAM_MODE_DMA_SG */
1074
1025static int mcam_setup_vb2(struct mcam_camera *cam) 1075static int mcam_setup_vb2(struct mcam_camera *cam)
1026{ 1076{
1027 struct vb2_queue *vq = &cam->vb_queue; 1077 struct vb2_queue *vq = &cam->vb_queue;
@@ -1032,21 +1082,35 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
1032 INIT_LIST_HEAD(&cam->buffers); 1082 INIT_LIST_HEAD(&cam->buffers);
1033 switch (cam->buffer_mode) { 1083 switch (cam->buffer_mode) {
1034 case B_DMA_contig: 1084 case B_DMA_contig:
1085#ifdef MCAM_MODE_DMA_CONTIG
1035 vq->ops = &mcam_vb2_ops; 1086 vq->ops = &mcam_vb2_ops;
1036 vq->mem_ops = &vb2_dma_contig_memops; 1087 vq->mem_ops = &vb2_dma_contig_memops;
1037 cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); 1088 cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
1038 vq->io_modes = VB2_MMAP | VB2_USERPTR; 1089 vq->io_modes = VB2_MMAP | VB2_USERPTR;
1090 cam->dma_setup = mcam_ctlr_dma_contig;
1091 cam->frame_complete = mcam_dma_contig_done;
1092#endif
1039 break; 1093 break;
1040 case B_DMA_sg: 1094 case B_DMA_sg:
1095#ifdef MCAM_MODE_DMA_SG
1041 vq->ops = &mcam_vb2_sg_ops; 1096 vq->ops = &mcam_vb2_sg_ops;
1042 vq->mem_ops = &vb2_dma_sg_memops; 1097 vq->mem_ops = &vb2_dma_sg_memops;
1043 vq->io_modes = VB2_MMAP | VB2_USERPTR; 1098 vq->io_modes = VB2_MMAP | VB2_USERPTR;
1099 cam->dma_setup = mcam_ctlr_dma_sg;
1100 cam->frame_complete = mcam_dma_sg_done;
1101#endif
1044 break; 1102 break;
1045 case B_vmalloc: 1103 case B_vmalloc:
1104#ifdef MCAM_MODE_VMALLOC
1105 tasklet_init(&cam->s_tasklet, mcam_frame_tasklet,
1106 (unsigned long) cam);
1046 vq->ops = &mcam_vb2_ops; 1107 vq->ops = &mcam_vb2_ops;
1047 vq->mem_ops = &vb2_vmalloc_memops; 1108 vq->mem_ops = &vb2_vmalloc_memops;
1048 vq->buf_struct_size = sizeof(struct mcam_vb_buffer); 1109 vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
1049 vq->io_modes = VB2_MMAP; 1110 vq->io_modes = VB2_MMAP;
1111 cam->dma_setup = mcam_ctlr_dma_vmalloc;
1112 cam->frame_complete = mcam_vmalloc_done;
1113#endif
1050 break; 1114 break;
1051 } 1115 }
1052 return vb2_queue_init(vq); 1116 return vb2_queue_init(vq);
@@ -1055,8 +1119,10 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
1055static void mcam_cleanup_vb2(struct mcam_camera *cam) 1119static void mcam_cleanup_vb2(struct mcam_camera *cam)
1056{ 1120{
1057 vb2_queue_release(&cam->vb_queue); 1121 vb2_queue_release(&cam->vb_queue);
1122#ifdef MCAM_MODE_DMA_CONTIG
1058 if (cam->buffer_mode == B_DMA_contig) 1123 if (cam->buffer_mode == B_DMA_contig)
1059 vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx); 1124 vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
1125#endif
1060} 1126}
1061 1127
1062 1128
@@ -1258,15 +1324,10 @@ static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
1258 /* 1324 /*
1259 * Make sure we have appropriate DMA buffers. 1325 * Make sure we have appropriate DMA buffers.
1260 */ 1326 */
1261 ret = -ENOMEM;
1262 if (cam->buffer_mode == B_vmalloc) { 1327 if (cam->buffer_mode == B_vmalloc) {
1263 if (cam->nbufs > 0 && 1328 ret = mcam_check_dma_buffers(cam);
1264 cam->dma_buf_size < cam->pix_format.sizeimage) 1329 if (ret)
1265 mcam_free_dma_bufs(cam); 1330 goto out;
1266 if (cam->nbufs == 0) {
1267 if (mcam_alloc_dma_bufs(cam, 0))
1268 goto out;
1269 }
1270 } 1331 }
1271 mcam_set_config_needed(cam, 1); 1332 mcam_set_config_needed(cam, 1);
1272 ret = 0; 1333 ret = 0;
@@ -1587,17 +1648,7 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame)
1587 /* 1648 /*
1588 * Process the frame and set up the next one. 1649 * Process the frame and set up the next one.
1589 */ 1650 */
1590 switch (cam->buffer_mode) { 1651 cam->frame_complete(cam, frame);
1591 case B_vmalloc:
1592 tasklet_schedule(&cam->s_tasklet);
1593 break;
1594 case B_DMA_contig:
1595 mcam_dma_contig_done(cam, frame);
1596 break;
1597 case B_DMA_sg:
1598 mcam_dma_sg_done(cam, frame);
1599 break;
1600 }
1601} 1652}
1602 1653
1603 1654
@@ -1663,6 +1714,22 @@ int mccic_register(struct mcam_camera *cam)
1663 int ret; 1714 int ret;
1664 1715
1665 /* 1716 /*
1717 * Validate the requested buffer mode.
1718 */
1719 if (buffer_mode >= 0)
1720 cam->buffer_mode = buffer_mode;
1721 if (cam->buffer_mode == B_DMA_sg &&
1722 cam->chip_id == V4L2_IDENT_CAFE) {
1723 printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, "
1724 "attempting vmalloc mode instead\n");
1725 cam->buffer_mode = B_vmalloc;
1726 }
1727 if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
1728 printk(KERN_ERR "marvell-cam: buffer mode %d unsupported\n",
1729 cam->buffer_mode);
1730 return -EINVAL;
1731 }
1732 /*
1666 * Register with V4L 1733 * Register with V4L
1667 */ 1734 */
1668 ret = v4l2_device_register(cam->dev, &cam->v4l2_dev); 1735 ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
@@ -1676,26 +1743,6 @@ int mccic_register(struct mcam_camera *cam)
1676 cam->mbus_code = mcam_def_mbus_code; 1743 cam->mbus_code = mcam_def_mbus_code;
1677 INIT_LIST_HEAD(&cam->dev_list); 1744 INIT_LIST_HEAD(&cam->dev_list);
1678 INIT_LIST_HEAD(&cam->buffers); 1745 INIT_LIST_HEAD(&cam->buffers);
1679 tasklet_init(&cam->s_tasklet, mcam_frame_tasklet, (unsigned long) cam);
1680 /*
1681 * User space may want to override the asked-for buffer mode;
1682 * here's hoping they know what they're doing.
1683 */
1684 if (buffer_mode == 0)
1685 cam->buffer_mode = B_vmalloc;
1686 else if (buffer_mode == 1)
1687 cam->buffer_mode = B_DMA_contig;
1688 else if (buffer_mode == 2) {
1689 if (cam->chip_id == V4L2_IDENT_ARMADA610)
1690 cam->buffer_mode = B_DMA_sg;
1691 else {
1692 printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O\n");
1693 cam->buffer_mode = B_vmalloc;
1694 }
1695 } else if (buffer_mode != -1)
1696 printk(KERN_ERR "marvell-cam: "
1697 "Strange module buffer mode %d - ignoring\n",
1698 buffer_mode);
1699 mcam_ctlr_init(cam); 1746 mcam_ctlr_init(cam);
1700 1747
1701 /* 1748 /*
diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h
index 9a39e08b752..aa552553723 100644
--- a/drivers/media/video/marvell-ccic/mcam-core.h
+++ b/drivers/media/video/marvell-ccic/mcam-core.h
@@ -11,6 +11,27 @@
11#include <media/v4l2-dev.h> 11#include <media/v4l2-dev.h>
12#include <media/videobuf2-core.h> 12#include <media/videobuf2-core.h>
13 13
14/*
15 * Create our own symbols for the supported buffer modes, but, for now,
16 * base them entirely on which videobuf2 options have been selected.
17 */
18#if defined(CONFIG_VIDEOBUF2_VMALLOC) || defined(CONFIG_VIDEOBUF2_VMALLOC_MODULE)
19#define MCAM_MODE_VMALLOC 1
20#endif
21
22#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG) || defined(CONFIG_VIDEOBUF2_DMA_CONTIG_MODULE)
23#define MCAM_MODE_DMA_CONTIG 1
24#endif
25
26#if defined(CONFIG_VIDEOBUF2_DMA_SG) || defined(CONFIG_VIDEOBUF2_DMA_SG_MODULE)
27#define MCAM_MODE_DMA_SG 1
28#endif
29
30#if !defined(MCAM_MODE_VMALLOC) && !defined(MCAM_MODE_DMA_CONTIG) && \
31 !defined(MCAM_MODE_DMA_SG)
32#error One of the videobuf buffer modes must be selected in the config
33#endif
34
14 35
15enum mcam_state { 36enum mcam_state {
16 S_NOTREADY, /* Not yet initialized */ 37 S_NOTREADY, /* Not yet initialized */
@@ -27,11 +48,33 @@ enum mcam_state {
27 */ 48 */
28enum mcam_buffer_mode { 49enum mcam_buffer_mode {
29 B_vmalloc = 0, 50 B_vmalloc = 0,
30 B_DMA_contig, 51 B_DMA_contig = 1,
31 B_DMA_sg 52 B_DMA_sg = 2
32}; 53};
33 54
34/* 55/*
56 * Is a given buffer mode supported by the current kernel configuration?
57 */
58static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode)
59{
60 switch (mode) {
61#ifdef MCAM_MODE_VMALLOC
62 case B_vmalloc:
63#endif
64#ifdef MCAM_MODE_DMA_CONTIG
65 case B_DMA_contig:
66#endif
67#ifdef MCAM_MODE_DMA_SG
68 case B_DMA_sg:
69#endif
70 return 1;
71 default:
72 return 0;
73 }
74}
75
76
77/*
35 * A description of one of our devices. 78 * A description of one of our devices.
36 * Locking: controlled by s_mutex. Certain fields, however, require 79 * Locking: controlled by s_mutex. Certain fields, however, require
37 * the dev_lock spinlock; they are marked as such by comments. 80 * the dev_lock spinlock; they are marked as such by comments.
@@ -79,21 +122,27 @@ struct mcam_camera {
79 struct vb2_queue vb_queue; 122 struct vb2_queue vb_queue;
80 struct list_head buffers; /* Available frames */ 123 struct list_head buffers; /* Available frames */
81 124
82 /* DMA buffers - vmalloc mode */
83 unsigned int nbufs; /* How many are alloc'd */ 125 unsigned int nbufs; /* How many are alloc'd */
84 int next_buf; /* Next to consume (dev_lock) */ 126 int next_buf; /* Next to consume (dev_lock) */
127
128 /* DMA buffers - vmalloc mode */
129#ifdef MCAM_MODE_VMALLOC
85 unsigned int dma_buf_size; /* allocated size */ 130 unsigned int dma_buf_size; /* allocated size */
86 void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ 131 void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */
87 dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ 132 dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
133 struct tasklet_struct s_tasklet;
134#endif
88 unsigned int sequence; /* Frame sequence number */ 135 unsigned int sequence; /* Frame sequence number */
89 unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ 136 unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */
90 137
91 /* DMA buffers - contiguous DMA mode */ 138 /* DMA buffers - DMA modes */
92 struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS]; 139 struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS];
93 struct vb2_alloc_ctx *vb_alloc_ctx; 140 struct vb2_alloc_ctx *vb_alloc_ctx;
94 unsigned short last_delivered; 141 unsigned short last_delivered;
95 142
96 struct tasklet_struct s_tasklet; 143 /* Mode-specific ops, set at open time */
144 void (*dma_setup)(struct mcam_camera *cam);
145 void (*frame_complete)(struct mcam_camera *cam, int frame);
97 146
98 /* Current operating parameters */ 147 /* Current operating parameters */
99 u32 sensor_type; /* Currently ov7670 only */ 148 u32 sensor_type; /* Currently ov7670 only */