提交 a9b36e85 编写于 作者: J Jonathan Corbet 提交者: Mauro Carvalho Chehab

[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: NJonathan Corbet <corbet@lwn.net>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 6c895d54
...@@ -14,6 +14,7 @@ config VIDEO_MMP_CAMERA ...@@ -14,6 +14,7 @@ config VIDEO_MMP_CAMERA
select VIDEO_OV7670 select VIDEO_OV7670
select I2C_GPIO select I2C_GPIO
select VIDEOBUF2_VMALLOC select VIDEOBUF2_VMALLOC
select VIDEOBUF2_DMA_CONTIG
---help--- ---help---
This is a Video4Linux2 driver for the integrated camera This is a Video4Linux2 driver for the integrated camera
controller found on Marvell Armada 610 application controller found on Marvell Armada 610 application
......
...@@ -481,6 +481,12 @@ static int cafe_pci_probe(struct pci_dev *pdev, ...@@ -481,6 +481,12 @@ static int cafe_pci_probe(struct pci_dev *pdev,
*/ */
mcam->clock_speed = 45; mcam->clock_speed = 45;
mcam->use_smbus = 1; mcam->use_smbus = 1;
/*
* Vmalloc mode for buffers is traditional with this driver.
* We *might* be able to run DMA_contig, especially on a system
* with CMA in it.
*/
mcam->buffer_mode = B_vmalloc;
/* /*
* Get set up on the PCI bus. * Get set up on the PCI bus.
*/ */
......
...@@ -25,9 +25,16 @@ ...@@ -25,9 +25,16 @@
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
#include <media/ov7670.h> #include <media/ov7670.h>
#include <media/videobuf2-vmalloc.h> #include <media/videobuf2-vmalloc.h>
#include <media/videobuf2-dma-contig.h>
#include "mcam-core.h" #include "mcam-core.h"
/*
* Basic frame stats - to be deleted shortly
*/
static int frames;
static int singles;
static int delivered;
/* /*
* Internal DMA buffer management. Since the controller cannot do S/G I/O, * 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,7 +55,8 @@ MODULE_PARM_DESC(alloc_bufs_at_read,
"Non-zero value causes DMA buffers to be allocated when the " "Non-zero value causes DMA buffers to be allocated when the "
"video capture device is read, rather than at module load " "video capture device is read, rather than at module load "
"time. This saves memory, but decreases the chances of " "time. This saves memory, but decreases the chances of "
"successfully getting those buffers."); "successfully getting those buffers. This parameter is "
"only used in the vmalloc buffer mode");
static int n_dma_bufs = 3; static int n_dma_bufs = 3;
module_param(n_dma_bufs, uint, 0644); module_param(n_dma_bufs, uint, 0644);
...@@ -82,6 +90,13 @@ MODULE_PARM_DESC(flip, ...@@ -82,6 +90,13 @@ MODULE_PARM_DESC(flip,
"If set, the sensor will be instructed to flip the image " "If set, the sensor will be instructed to flip the image "
"vertically."); "vertically.");
static int buffer_mode = -1;
module_param(buffer_mode, int, 0444);
MODULE_PARM_DESC(buffer_mode,
"Set the buffer mode to be used; default is to go with what "
"the platform driver asks for. Set to 0 for vmalloc, 1 for "
"DMA contiguous.");
/* /*
* Status flags. Always manipulated with bit operations. * Status flags. Always manipulated with bit operations.
*/ */
...@@ -90,6 +105,7 @@ MODULE_PARM_DESC(flip, ...@@ -90,6 +105,7 @@ MODULE_PARM_DESC(flip,
#define CF_BUF2_VALID 2 #define CF_BUF2_VALID 2
#define CF_DMA_ACTIVE 3 /* A frame is incoming */ #define CF_DMA_ACTIVE 3 /* A frame is incoming */
#define CF_CONFIG_NEEDED 4 /* Must configure hardware */ #define CF_CONFIG_NEEDED 4 /* Must configure hardware */
#define CF_SINGLE_BUFFER 5 /* Running with a single buffer */
#define sensor_call(cam, o, f, args...) \ #define sensor_call(cam, o, f, args...) \
v4l2_subdev_call(cam->sensor, o, f, ##args) 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,10 +213,9 @@ static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
*/ */
/* /*
* Do everything we think we need to have the interface operating * Set up DMA buffers when operating in vmalloc mode
* according to the desired format.
*/ */
static void mcam_ctlr_dma(struct mcam_camera *cam) static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam)
{ {
/* /*
* Store the first two Y buffers (we aren't supporting * Store the first two Y buffers (we aren't supporting
...@@ -219,6 +234,57 @@ static void mcam_ctlr_dma(struct mcam_camera *cam) ...@@ -219,6 +234,57 @@ static void mcam_ctlr_dma(struct mcam_camera *cam)
mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */ mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */
} }
/*
* Set up a contiguous buffer for the given frame. Here also is where
* the underrun strategy is set: if there is no buffer available, reuse
* the buffer from the other BAR and set the CF_SINGLE_BUFFER flag to
* keep the interrupt handler from giving that buffer back to user
* space. In this way, we always have a buffer to DMA to and don't
* have to try to play games stopping and restarting the controller.
*/
static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
{
struct mcam_vb_buffer *buf;
/*
* If there are no available buffers, go into single mode
*/
if (list_empty(&cam->buffers)) {
buf = cam->vb_bufs[frame ^ 0x1];
cam->vb_bufs[frame] = buf;
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
set_bit(CF_SINGLE_BUFFER, &cam->flags);
singles++;
return;
}
/*
* OK, we have a buffer we can use.
*/
buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
list_del_init(&buf->queue);
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
vb2_dma_contig_plane_paddr(&buf->vb_buf, 0));
cam->vb_bufs[frame] = buf;
clear_bit(CF_SINGLE_BUFFER, &cam->flags);
}
static void mcam_ctlr_dma_contig(struct mcam_camera *cam)
{
mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
cam->nbufs = 2;
mcam_set_contig_buffer(cam, 0);
mcam_set_contig_buffer(cam, 1);
}
static void mcam_ctlr_dma(struct mcam_camera *cam)
{
if (cam->buffer_mode == B_DMA_contig)
mcam_ctlr_dma_contig(cam);
else
mcam_ctlr_dma_vmalloc(cam);
}
static void mcam_ctlr_image(struct mcam_camera *cam) static void mcam_ctlr_image(struct mcam_camera *cam)
{ {
int imgsz; int imgsz;
...@@ -542,7 +608,7 @@ static void mcam_free_dma_bufs(struct mcam_camera *cam) ...@@ -542,7 +608,7 @@ static void mcam_free_dma_bufs(struct mcam_camera *cam)
/* /*
* Get everything ready, and start grabbing frames. * Get everything ready, and start grabbing frames.
*/ */
static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state) static int mcam_read_setup(struct mcam_camera *cam)
{ {
int ret; int ret;
unsigned long flags; unsigned long flags;
...@@ -551,9 +617,9 @@ static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state) ...@@ -551,9 +617,9 @@ static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state)
* Configuration. If we still don't have DMA buffers, * Configuration. If we still don't have DMA buffers,
* make one last, desperate attempt. * make one last, desperate attempt.
*/ */
if (cam->nbufs == 0) if (cam->buffer_mode == B_vmalloc && cam->nbufs == 0 &&
if (mcam_alloc_dma_bufs(cam, 0)) mcam_alloc_dma_bufs(cam, 0))
return -ENOMEM; return -ENOMEM;
if (mcam_needs_config(cam)) { if (mcam_needs_config(cam)) {
mcam_cam_configure(cam); mcam_cam_configure(cam);
...@@ -568,7 +634,7 @@ static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state) ...@@ -568,7 +634,7 @@ static int mcam_read_setup(struct mcam_camera *cam, enum mcam_state state)
spin_lock_irqsave(&cam->dev_lock, flags); spin_lock_irqsave(&cam->dev_lock, flags);
mcam_reset_buffers(cam); mcam_reset_buffers(cam);
mcam_ctlr_irq_enable(cam); mcam_ctlr_irq_enable(cam);
cam->state = state; cam->state = S_STREAMING;
mcam_ctlr_start(cam); mcam_ctlr_start(cam);
spin_unlock_irqrestore(&cam->dev_lock, flags); spin_unlock_irqrestore(&cam->dev_lock, flags);
return 0; return 0;
...@@ -587,8 +653,10 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs, ...@@ -587,8 +653,10 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq, unsigned int *nbufs,
sizes[0] = cam->pix_format.sizeimage; sizes[0] = cam->pix_format.sizeimage;
*num_planes = 1; /* Someday we have to support planar formats... */ *num_planes = 1; /* Someday we have to support planar formats... */
if (*nbufs < 2 || *nbufs > 32) if (*nbufs < 3 || *nbufs > 32)
*nbufs = 6; /* semi-arbitrary numbers */ *nbufs = 3; /* semi-arbitrary numbers */
if (cam->buffer_mode == B_DMA_contig)
alloc_ctxs[0] = cam->vb_alloc_ctx;
return 0; return 0;
} }
...@@ -605,10 +673,14 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb) ...@@ -605,10 +673,14 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
struct mcam_vb_buffer *mvb = vb_to_mvb(vb); struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
unsigned long flags; unsigned long flags;
int start;
spin_lock_irqsave(&cam->dev_lock, flags); spin_lock_irqsave(&cam->dev_lock, flags);
list_add(&cam->buffers, &mvb->queue); start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
list_add(&mvb->queue, &cam->buffers);
spin_unlock_irqrestore(&cam->dev_lock, flags); spin_unlock_irqrestore(&cam->dev_lock, flags);
if (start)
mcam_read_setup(cam);
} }
/* /*
...@@ -636,13 +708,22 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq) ...@@ -636,13 +708,22 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
static int mcam_vb_start_streaming(struct vb2_queue *vq) static int mcam_vb_start_streaming(struct vb2_queue *vq)
{ {
struct mcam_camera *cam = vb2_get_drv_priv(vq); struct mcam_camera *cam = vb2_get_drv_priv(vq);
int ret = -EINVAL;
if (cam->state == S_IDLE) { if (cam->state != S_IDLE)
cam->sequence = 0; return -EINVAL;
ret = mcam_read_setup(cam, S_STREAMING); cam->sequence = 0;
/*
* Videobuf2 sneakily hoards all the buffers and won't
* give them to us until *after* streaming starts. But
* we can't actually start streaming until we have a
* destination. So go into a wait state and hope they
* give us buffers soon.
*/
if (cam->buffer_mode != B_vmalloc && list_empty(&cam->buffers)) {
cam->state = S_BUFWAIT;
return 0;
} }
return ret; return mcam_read_setup(cam);
} }
static int mcam_vb_stop_streaming(struct vb2_queue *vq) 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,6 +731,11 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
struct mcam_camera *cam = vb2_get_drv_priv(vq); struct mcam_camera *cam = vb2_get_drv_priv(vq);
unsigned long flags; unsigned long flags;
if (cam->state == S_BUFWAIT) {
/* They never gave us buffers */
cam->state = S_IDLE;
return 0;
}
if (cam->state != S_STREAMING) if (cam->state != S_STREAMING)
return -EINVAL; return -EINVAL;
mcam_ctlr_stop_dma(cam); mcam_ctlr_stop_dma(cam);
...@@ -683,7 +769,11 @@ static int mcam_setup_vb2(struct mcam_camera *cam) ...@@ -683,7 +769,11 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
vq->io_modes = VB2_MMAP; /* Add userptr */ vq->io_modes = VB2_MMAP; /* Add userptr */
vq->drv_priv = cam; vq->drv_priv = cam;
vq->ops = &mcam_vb2_ops; vq->ops = &mcam_vb2_ops;
vq->mem_ops = &vb2_vmalloc_memops; if (cam->buffer_mode == B_DMA_contig) {
vq->mem_ops = &vb2_dma_contig_memops;
cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
} else
vq->mem_ops = &vb2_vmalloc_memops;
vq->buf_struct_size = sizeof(struct mcam_vb_buffer); vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
return vb2_queue_init(vq); return vb2_queue_init(vq);
...@@ -692,6 +782,8 @@ static int mcam_setup_vb2(struct mcam_camera *cam) ...@@ -692,6 +782,8 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
static void mcam_cleanup_vb2(struct mcam_camera *cam) static void mcam_cleanup_vb2(struct mcam_camera *cam)
{ {
vb2_queue_release(&cam->vb_queue); vb2_queue_release(&cam->vb_queue);
if (cam->buffer_mode == B_DMA_contig)
vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
} }
static ssize_t mcam_v4l_read(struct file *filp, static ssize_t mcam_v4l_read(struct file *filp,
...@@ -809,6 +901,7 @@ static int mcam_v4l_open(struct file *filp) ...@@ -809,6 +901,7 @@ static int mcam_v4l_open(struct file *filp)
filp->private_data = cam; filp->private_data = cam;
frames = singles = delivered = 0;
mutex_lock(&cam->s_mutex); mutex_lock(&cam->s_mutex);
if (cam->users == 0) { if (cam->users == 0) {
ret = mcam_setup_vb2(cam); ret = mcam_setup_vb2(cam);
...@@ -829,6 +922,8 @@ static int mcam_v4l_release(struct file *filp) ...@@ -829,6 +922,8 @@ static int mcam_v4l_release(struct file *filp)
{ {
struct mcam_camera *cam = filp->private_data; struct mcam_camera *cam = filp->private_data;
cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames,
singles, delivered);
mutex_lock(&cam->s_mutex); mutex_lock(&cam->s_mutex);
(cam->users)--; (cam->users)--;
if (filp == cam->owner) { if (filp == cam->owner) {
...@@ -838,7 +933,7 @@ static int mcam_v4l_release(struct file *filp) ...@@ -838,7 +933,7 @@ static int mcam_v4l_release(struct file *filp)
if (cam->users == 0) { if (cam->users == 0) {
mcam_cleanup_vb2(cam); mcam_cleanup_vb2(cam);
mcam_ctlr_power_down(cam); mcam_ctlr_power_down(cam);
if (alloc_bufs_at_read) if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
mcam_free_dma_bufs(cam); mcam_free_dma_bufs(cam);
} }
mutex_unlock(&cam->s_mutex); mutex_unlock(&cam->s_mutex);
...@@ -993,18 +1088,17 @@ static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv, ...@@ -993,18 +1088,17 @@ static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
* Make sure we have appropriate DMA buffers. * Make sure we have appropriate DMA buffers.
*/ */
ret = -ENOMEM; ret = -ENOMEM;
if (cam->nbufs > 0 && cam->dma_buf_size < cam->pix_format.sizeimage) if (cam->buffer_mode == B_vmalloc) {
mcam_free_dma_bufs(cam); if (cam->nbufs > 0 &&
if (cam->nbufs == 0) { cam->dma_buf_size < cam->pix_format.sizeimage)
if (mcam_alloc_dma_bufs(cam, 0)) mcam_free_dma_bufs(cam);
goto out; if (cam->nbufs == 0) {
if (mcam_alloc_dma_bufs(cam, 0))
goto out;
}
} }
/* mcam_set_config_needed(cam, 1);
* It looks like this might work, so let's program the sensor. ret = 0;
*/
ret = mcam_cam_configure(cam);
if (!ret)
ret = mcam_ctlr_configure(cam);
out: out:
mutex_unlock(&cam->s_mutex); mutex_unlock(&cam->s_mutex);
return ret; return ret;
...@@ -1214,7 +1308,20 @@ static struct video_device mcam_v4l_template = { ...@@ -1214,7 +1308,20 @@ static struct video_device mcam_v4l_template = {
*/ */
static void mcam_buffer_done(struct mcam_camera *cam, int frame,
struct vb2_buffer *vbuf)
{
vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage;
vbuf->v4l2_buf.sequence = cam->buf_seq[frame];
vbuf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
vbuf->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage);
vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE);
}
/*
* Copy data out to user space in the vmalloc case
*/
static void mcam_frame_tasklet(unsigned long data) static void mcam_frame_tasklet(unsigned long data)
{ {
struct mcam_camera *cam = (struct mcam_camera *) data; struct mcam_camera *cam = (struct mcam_camera *) data;
...@@ -1232,8 +1339,11 @@ static void mcam_frame_tasklet(unsigned long data) ...@@ -1232,8 +1339,11 @@ static void mcam_frame_tasklet(unsigned long data)
cam->next_buf = 0; cam->next_buf = 0;
if (!test_bit(bufno, &cam->flags)) if (!test_bit(bufno, &cam->flags))
continue; continue;
if (list_empty(&cam->buffers)) if (list_empty(&cam->buffers)) {
singles++;
break; /* Leave it valid, hope for better later */ break; /* Leave it valid, hope for better later */
}
delivered++;
clear_bit(bufno, &cam->flags); clear_bit(bufno, &cam->flags);
buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
queue); queue);
...@@ -1244,18 +1354,25 @@ static void mcam_frame_tasklet(unsigned long data) ...@@ -1244,18 +1354,25 @@ static void mcam_frame_tasklet(unsigned long data)
spin_unlock_irqrestore(&cam->dev_lock, flags); spin_unlock_irqrestore(&cam->dev_lock, flags);
memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno], memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno],
cam->pix_format.sizeimage); cam->pix_format.sizeimage);
buf->vb_buf.v4l2_buf.bytesused = cam->pix_format.sizeimage; mcam_buffer_done(cam, bufno, &buf->vb_buf);
buf->vb_buf.v4l2_buf.sequence = cam->buf_seq[bufno];
buf->vb_buf.v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
buf->vb_buf.v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
vb2_set_plane_payload(&buf->vb_buf, 0,
cam->pix_format.sizeimage);
vb2_buffer_done(&buf->vb_buf, VB2_BUF_STATE_DONE);
spin_lock_irqsave(&cam->dev_lock, flags); spin_lock_irqsave(&cam->dev_lock, flags);
} }
spin_unlock_irqrestore(&cam->dev_lock, flags); spin_unlock_irqrestore(&cam->dev_lock, flags);
} }
/*
* For direct DMA, mark the buffer ready and set up another one.
*/
static void mcam_dma_complete(struct mcam_camera *cam, int frame)
{
struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) {
delivered++;
mcam_buffer_done(cam, frame, &buf->vb_buf);
}
mcam_set_contig_buffer(cam, frame);
}
static void mcam_frame_complete(struct mcam_camera *cam, int frame) 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,21 +1382,20 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame)
*/ */
set_bit(frame, &cam->flags); set_bit(frame, &cam->flags);
clear_bit(CF_DMA_ACTIVE, &cam->flags); clear_bit(CF_DMA_ACTIVE, &cam->flags);
if (cam->next_buf < 0) cam->next_buf = frame;
cam->next_buf = frame;
cam->buf_seq[frame] = ++(cam->sequence); cam->buf_seq[frame] = ++(cam->sequence);
cam->last_delivered = frame;
frames++;
switch (cam->state) { switch (cam->state) {
/* /*
* For the streaming case, we defer the real work to the * We're streaming and have a ready frame, hand it back
* camera tasklet.
*
* FIXME: if the application is not consuming the buffers,
* we should eventually put things on hold and restart in
* vidioc_dqbuf().
*/ */
case S_STREAMING: case S_STREAMING:
tasklet_schedule(&cam->s_tasklet); if (cam->buffer_mode == B_vmalloc)
tasklet_schedule(&cam->s_tasklet);
else
mcam_dma_complete(cam, frame);
break; break;
default: default:
...@@ -1356,7 +1472,18 @@ int mccic_register(struct mcam_camera *cam) ...@@ -1356,7 +1472,18 @@ int mccic_register(struct mcam_camera *cam)
INIT_LIST_HEAD(&cam->dev_list); INIT_LIST_HEAD(&cam->dev_list);
INIT_LIST_HEAD(&cam->buffers); INIT_LIST_HEAD(&cam->buffers);
tasklet_init(&cam->s_tasklet, mcam_frame_tasklet, (unsigned long) cam); 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 != -1)
printk(KERN_ERR "marvel-cam: "
"Strange module buffer mode %d - ignoring\n",
buffer_mode);
mcam_ctlr_init(cam); mcam_ctlr_init(cam);
/* /*
...@@ -1390,7 +1517,7 @@ int mccic_register(struct mcam_camera *cam) ...@@ -1390,7 +1517,7 @@ int mccic_register(struct mcam_camera *cam)
/* /*
* If so requested, try to get our DMA buffers now. * If so requested, try to get our DMA buffers now.
*/ */
if (!alloc_bufs_at_read) { if (cam->buffer_mode == B_vmalloc && !alloc_bufs_at_read) {
if (mcam_alloc_dma_bufs(cam, 1)) if (mcam_alloc_dma_bufs(cam, 1))
cam_warn(cam, "Unable to alloc DMA buffers at load" cam_warn(cam, "Unable to alloc DMA buffers at load"
" will try again later."); " will try again later.");
...@@ -1418,7 +1545,8 @@ void mccic_shutdown(struct mcam_camera *cam) ...@@ -1418,7 +1545,8 @@ void mccic_shutdown(struct mcam_camera *cam)
mcam_ctlr_power_down(cam); mcam_ctlr_power_down(cam);
} }
vb2_queue_release(&cam->vb_queue); vb2_queue_release(&cam->vb_queue);
mcam_free_dma_bufs(cam); if (cam->buffer_mode == B_vmalloc)
mcam_free_dma_bufs(cam);
video_unregister_device(&cam->vdev); video_unregister_device(&cam->vdev);
v4l2_device_unregister(&cam->v4l2_dev); v4l2_device_unregister(&cam->v4l2_dev);
} }
...@@ -1452,7 +1580,7 @@ int mccic_resume(struct mcam_camera *cam) ...@@ -1452,7 +1580,7 @@ int mccic_resume(struct mcam_camera *cam)
set_bit(CF_CONFIG_NEEDED, &cam->flags); set_bit(CF_CONFIG_NEEDED, &cam->flags);
if (cam->state == S_STREAMING) if (cam->state == S_STREAMING)
ret = mcam_read_setup(cam, cam->state); ret = mcam_read_setup(cam);
return ret; return ret;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
...@@ -27,10 +27,20 @@ enum mcam_state { ...@@ -27,10 +27,20 @@ enum mcam_state {
S_NOTREADY, /* Not yet initialized */ S_NOTREADY, /* Not yet initialized */
S_IDLE, /* Just hanging around */ S_IDLE, /* Just hanging around */
S_FLAKED, /* Some sort of problem */ S_FLAKED, /* Some sort of problem */
S_STREAMING /* Streaming data */ S_STREAMING, /* Streaming data */
S_BUFWAIT /* streaming requested but no buffers yet */
}; };
#define MAX_DMA_BUFS 3 #define MAX_DMA_BUFS 3
/*
* Different platforms work best with different buffer modes, so we
* let the platform pick.
*/
enum mcam_buffer_mode {
B_vmalloc = 0,
B_DMA_contig
};
/* /*
* A description of one of our devices. * A description of one of our devices.
* Locking: controlled by s_mutex. Certain fields, however, require * Locking: controlled by s_mutex. Certain fields, however, require
...@@ -49,7 +59,7 @@ struct mcam_camera { ...@@ -49,7 +59,7 @@ struct mcam_camera {
unsigned int chip_id; unsigned int chip_id;
short int clock_speed; /* Sensor clock speed, default 30 */ short int clock_speed; /* Sensor clock speed, default 30 */
short int use_smbus; /* SMBUS or straight I2c? */ short int use_smbus; /* SMBUS or straight I2c? */
enum mcam_buffer_mode buffer_mode;
/* /*
* Callbacks from the core to the platform code. * Callbacks from the core to the platform code.
*/ */
...@@ -79,7 +89,7 @@ struct mcam_camera { ...@@ -79,7 +89,7 @@ struct mcam_camera {
struct vb2_queue vb_queue; struct vb2_queue vb_queue;
struct list_head buffers; /* Available frames */ struct list_head buffers; /* Available frames */
/* DMA buffers */ /* DMA buffers - vmalloc mode */
unsigned int nbufs; /* How many are alloc'd */ unsigned int nbufs; /* How many are alloc'd */
int next_buf; /* Next to consume (dev_lock) */ int next_buf; /* Next to consume (dev_lock) */
unsigned int dma_buf_size; /* allocated size */ unsigned int dma_buf_size; /* allocated size */
...@@ -88,6 +98,11 @@ struct mcam_camera { ...@@ -88,6 +98,11 @@ struct mcam_camera {
unsigned int sequence; /* Frame sequence number */ unsigned int sequence; /* Frame sequence number */
unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */
/* DMA buffers - contiguous DMA mode */
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; struct tasklet_struct s_tasklet;
/* Current operating parameters */ /* Current operating parameters */
......
...@@ -180,6 +180,7 @@ static int mmpcam_probe(struct platform_device *pdev) ...@@ -180,6 +180,7 @@ static int mmpcam_probe(struct platform_device *pdev)
mcam->dev = &pdev->dev; mcam->dev = &pdev->dev;
mcam->use_smbus = 0; mcam->use_smbus = 0;
mcam->chip_id = V4L2_IDENT_ARMADA610; mcam->chip_id = V4L2_IDENT_ARMADA610;
mcam->buffer_mode = B_vmalloc; /* Switch to dma */
spin_lock_init(&mcam->dev_lock); spin_lock_init(&mcam->dev_lock);
/* /*
* Get our I/O memory. * Get our I/O memory.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册