Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 261533
b: refs/heads/master
c: 7498469
h: refs/heads/master
i:
  261531: 29509e2
v: v3
  • Loading branch information
Jonathan Corbet authored and Mauro Carvalho Chehab committed Jul 27, 2011
1 parent e2b7616 commit 0c84d04
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 60 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 221a8248b9ca62a7304115782dca46a3f014f454
refs/heads/master: 7498469f619e1ba380fc90042a2b1736c7c6942c
3 changes: 0 additions & 3 deletions trunk/drivers/media/video/marvell-ccic/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ config VIDEO_CAFE_CCIC
select VIDEO_OV7670
select VIDEOBUF2_VMALLOC
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_DMA_SG
---help---
This is a video4linux2 driver for the Marvell 88ALP01 integrated
CMOS camera controller. This is the controller found on first-
Expand All @@ -15,8 +14,6 @@ config VIDEO_MMP_CAMERA
depends on ARCH_MMP && I2C && VIDEO_V4L2
select VIDEO_OV7670
select I2C_GPIO
select VIDEOBUF2_VMALLOC
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_DMA_SG
---help---
This is a Video4Linux2 driver for the integrated camera
Expand Down
149 changes: 98 additions & 51 deletions trunk/drivers/media/video/marvell-ccic/mcam-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static int frames;
static int singles;
static int delivered;

#ifdef MCAM_MODE_VMALLOC
/*
* Internal DMA buffer management. Since the controller cannot do S/G I/O,
* we must have physically contiguous buffers to bring frames into.
Expand Down Expand Up @@ -71,6 +72,10 @@ MODULE_PARM_DESC(dma_buf_size,
"The size of the allocated DMA buffers. If actual operating "
"parameters require larger buffers, an attempt to reallocate "
"will be made.");
#else /* MCAM_MODE_VMALLOC */
static const int alloc_bufs_at_read = 0;
static const int n_dma_bufs = 3; /* Used by S/G_PARM */
#endif /* MCAM_MODE_VMALLOC */

static int flip;
module_param(flip, bool, 0444);
Expand Down Expand Up @@ -256,6 +261,8 @@ static void mcam_ctlr_stop(struct mcam_camera *cam)
}

/* ------------------------------------------------------------------- */

#ifdef MCAM_MODE_VMALLOC
/*
* Code specific to the vmalloc buffer mode.
*/
Expand Down Expand Up @@ -381,6 +388,46 @@ static void mcam_frame_tasklet(unsigned long data)
}


/*
* Make sure our allocated buffers are up to the task.
*/
static int mcam_check_dma_buffers(struct mcam_camera *cam)
{
if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage)
mcam_free_dma_bufs(cam);
if (cam->nbufs == 0)
return mcam_alloc_dma_bufs(cam, 0);
return 0;
}

static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
{
tasklet_schedule(&cam->s_tasklet);
}

#else /* MCAM_MODE_VMALLOC */

static inline int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
{
return 0;
}

static inline void mcam_free_dma_bufs(struct mcam_camera *cam)
{
return;
}

static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
{
return 0;
}



#endif /* MCAM_MODE_VMALLOC */


#ifdef MCAM_MODE_DMA_CONTIG
/* ---------------------------------------------------------------------- */
/*
* DMA-contiguous code.
Expand Down Expand Up @@ -444,8 +491,9 @@ static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
mcam_set_contig_buffer(cam, frame);
}

#endif /* MCAM_MODE_DMA_CONTIG */


#ifdef MCAM_MODE_DMA_SG
/* ---------------------------------------------------------------------- */
/*
* Scatter/gather-specific code.
Expand Down Expand Up @@ -540,6 +588,14 @@ static void mcam_sg_restart(struct mcam_camera *cam)
clear_bit(CF_SG_RESTART, &cam->flags);
}

#else /* MCAM_MODE_DMA_SG */

static inline void mcam_sg_restart(struct mcam_camera *cam)
{
return;
}

#endif /* MCAM_MODE_DMA_SG */

/* ---------------------------------------------------------------------- */
/*
Expand Down Expand Up @@ -605,17 +661,7 @@ static int mcam_ctlr_configure(struct mcam_camera *cam)
unsigned long flags;

spin_lock_irqsave(&cam->dev_lock, flags);
switch (cam->buffer_mode) {
case B_vmalloc:
mcam_ctlr_dma_vmalloc(cam);
break;
case B_DMA_contig:
mcam_ctlr_dma_contig(cam);
break;
case B_DMA_sg:
mcam_ctlr_dma_sg(cam);
break;
}
cam->dma_setup(cam);
mcam_ctlr_image(cam);
mcam_set_config_needed(cam, 0);
clear_bit(CF_SG_RESTART, &cam->flags);
Expand Down Expand Up @@ -948,6 +994,8 @@ static const struct vb2_ops mcam_vb2_ops = {
.wait_finish = mcam_vb_wait_finish,
};


#ifdef MCAM_MODE_DMA_SG
/*
* Scatter/gather mode uses all of the above functions plus a
* few extras to deal with DMA mapping.
Expand Down Expand Up @@ -1022,6 +1070,8 @@ static const struct vb2_ops mcam_vb2_sg_ops = {
.wait_finish = mcam_vb_wait_finish,
};

#endif /* MCAM_MODE_DMA_SG */

static int mcam_setup_vb2(struct mcam_camera *cam)
{
struct vb2_queue *vq = &cam->vb_queue;
Expand All @@ -1032,21 +1082,35 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
INIT_LIST_HEAD(&cam->buffers);
switch (cam->buffer_mode) {
case B_DMA_contig:
#ifdef MCAM_MODE_DMA_CONTIG
vq->ops = &mcam_vb2_ops;
vq->mem_ops = &vb2_dma_contig_memops;
cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
vq->io_modes = VB2_MMAP | VB2_USERPTR;
cam->dma_setup = mcam_ctlr_dma_contig;
cam->frame_complete = mcam_dma_contig_done;
#endif
break;
case B_DMA_sg:
#ifdef MCAM_MODE_DMA_SG
vq->ops = &mcam_vb2_sg_ops;
vq->mem_ops = &vb2_dma_sg_memops;
vq->io_modes = VB2_MMAP | VB2_USERPTR;
cam->dma_setup = mcam_ctlr_dma_sg;
cam->frame_complete = mcam_dma_sg_done;
#endif
break;
case B_vmalloc:
#ifdef MCAM_MODE_VMALLOC
tasklet_init(&cam->s_tasklet, mcam_frame_tasklet,
(unsigned long) cam);
vq->ops = &mcam_vb2_ops;
vq->mem_ops = &vb2_vmalloc_memops;
vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
vq->io_modes = VB2_MMAP;
cam->dma_setup = mcam_ctlr_dma_vmalloc;
cam->frame_complete = mcam_vmalloc_done;
#endif
break;
}
return vb2_queue_init(vq);
Expand All @@ -1055,8 +1119,10 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
static void mcam_cleanup_vb2(struct mcam_camera *cam)
{
vb2_queue_release(&cam->vb_queue);
#ifdef MCAM_MODE_DMA_CONTIG
if (cam->buffer_mode == B_DMA_contig)
vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
#endif
}


Expand Down Expand Up @@ -1258,15 +1324,10 @@ static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
/*
* Make sure we have appropriate DMA buffers.
*/
ret = -ENOMEM;
if (cam->buffer_mode == B_vmalloc) {
if (cam->nbufs > 0 &&
cam->dma_buf_size < cam->pix_format.sizeimage)
mcam_free_dma_bufs(cam);
if (cam->nbufs == 0) {
if (mcam_alloc_dma_bufs(cam, 0))
goto out;
}
ret = mcam_check_dma_buffers(cam);
if (ret)
goto out;
}
mcam_set_config_needed(cam, 1);
ret = 0;
Expand Down Expand Up @@ -1587,17 +1648,7 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame)
/*
* Process the frame and set up the next one.
*/
switch (cam->buffer_mode) {
case B_vmalloc:
tasklet_schedule(&cam->s_tasklet);
break;
case B_DMA_contig:
mcam_dma_contig_done(cam, frame);
break;
case B_DMA_sg:
mcam_dma_sg_done(cam, frame);
break;
}
cam->frame_complete(cam, frame);
}


Expand Down Expand Up @@ -1662,6 +1713,22 @@ int mccic_register(struct mcam_camera *cam)
};
int ret;

/*
* Validate the requested buffer mode.
*/
if (buffer_mode >= 0)
cam->buffer_mode = buffer_mode;
if (cam->buffer_mode == B_DMA_sg &&
cam->chip_id == V4L2_IDENT_CAFE) {
printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, "
"attempting vmalloc mode instead\n");
cam->buffer_mode = B_vmalloc;
}
if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
printk(KERN_ERR "marvell-cam: buffer mode %d unsupported\n",
cam->buffer_mode);
return -EINVAL;
}
/*
* Register with V4L
*/
Expand All @@ -1676,26 +1743,6 @@ int mccic_register(struct mcam_camera *cam)
cam->mbus_code = mcam_def_mbus_code;
INIT_LIST_HEAD(&cam->dev_list);
INIT_LIST_HEAD(&cam->buffers);
tasklet_init(&cam->s_tasklet, mcam_frame_tasklet, (unsigned long) cam);
/*
* User space may want to override the asked-for buffer mode;
* here's hoping they know what they're doing.
*/
if (buffer_mode == 0)
cam->buffer_mode = B_vmalloc;
else if (buffer_mode == 1)
cam->buffer_mode = B_DMA_contig;
else if (buffer_mode == 2) {
if (cam->chip_id == V4L2_IDENT_ARMADA610)
cam->buffer_mode = B_DMA_sg;
else {
printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O\n");
cam->buffer_mode = B_vmalloc;
}
} else if (buffer_mode != -1)
printk(KERN_ERR "marvell-cam: "
"Strange module buffer mode %d - ignoring\n",
buffer_mode);
mcam_ctlr_init(cam);

/*
Expand Down
59 changes: 54 additions & 5 deletions trunk/drivers/media/video/marvell-ccic/mcam-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@
#include <media/v4l2-dev.h>
#include <media/videobuf2-core.h>

/*
* Create our own symbols for the supported buffer modes, but, for now,
* base them entirely on which videobuf2 options have been selected.
*/
#if defined(CONFIG_VIDEOBUF2_VMALLOC) || defined(CONFIG_VIDEOBUF2_VMALLOC_MODULE)
#define MCAM_MODE_VMALLOC 1
#endif

#if defined(CONFIG_VIDEOBUF2_DMA_CONTIG) || defined(CONFIG_VIDEOBUF2_DMA_CONTIG_MODULE)
#define MCAM_MODE_DMA_CONTIG 1
#endif

#if defined(CONFIG_VIDEOBUF2_DMA_SG) || defined(CONFIG_VIDEOBUF2_DMA_SG_MODULE)
#define MCAM_MODE_DMA_SG 1
#endif

#if !defined(MCAM_MODE_VMALLOC) && !defined(MCAM_MODE_DMA_CONTIG) && \
!defined(MCAM_MODE_DMA_SG)
#error One of the videobuf buffer modes must be selected in the config
#endif


enum mcam_state {
S_NOTREADY, /* Not yet initialized */
Expand All @@ -27,10 +48,32 @@ enum mcam_state {
*/
enum mcam_buffer_mode {
B_vmalloc = 0,
B_DMA_contig,
B_DMA_sg
B_DMA_contig = 1,
B_DMA_sg = 2
};

/*
* Is a given buffer mode supported by the current kernel configuration?
*/
static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode)
{
switch (mode) {
#ifdef MCAM_MODE_VMALLOC
case B_vmalloc:
#endif
#ifdef MCAM_MODE_DMA_CONTIG
case B_DMA_contig:
#endif
#ifdef MCAM_MODE_DMA_SG
case B_DMA_sg:
#endif
return 1;
default:
return 0;
}
}


/*
* A description of one of our devices.
* Locking: controlled by s_mutex. Certain fields, however, require
Expand Down Expand Up @@ -79,21 +122,27 @@ struct mcam_camera {
struct vb2_queue vb_queue;
struct list_head buffers; /* Available frames */

/* DMA buffers - vmalloc mode */
unsigned int nbufs; /* How many are alloc'd */
int next_buf; /* Next to consume (dev_lock) */

/* DMA buffers - vmalloc mode */
#ifdef MCAM_MODE_VMALLOC
unsigned int dma_buf_size; /* allocated size */
void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */
dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */
struct tasklet_struct s_tasklet;
#endif
unsigned int sequence; /* Frame sequence number */
unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */

/* DMA buffers - contiguous DMA mode */
/* DMA buffers - DMA modes */
struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS];
struct vb2_alloc_ctx *vb_alloc_ctx;
unsigned short last_delivered;

struct tasklet_struct s_tasklet;
/* Mode-specific ops, set at open time */
void (*dma_setup)(struct mcam_camera *cam);
void (*frame_complete)(struct mcam_camera *cam, int frame);

/* Current operating parameters */
u32 sensor_type; /* Currently ov7670 only */
Expand Down

0 comments on commit 0c84d04

Please sign in to comment.