static int flexio_capture_dma_submit(struct imx_flexio_capture_dev *fcam)
{
struct dma_chan *chan = fcam->hw.dma;
struct dma_async_tx_descriptor *txdesc;
struct v4l2_pix_format *fmt;
dma_addr_t dest_addr;
if (!fcam->pipe.active)
return -EINVAL;
fmt = &fcam->pipe.pixfmt;
dest_addr = vb2_dma_contig_plane_dma_addr(&fcam->pipe.active->v4l2_buf.vb2_buf, 0);
txdesc = dmaengine_prep_slave_single(chan, dest_addr, fmt->sizeimage, DMA_DEV_TO_MEM,DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!txdesc) {
dev_err(fcam->dev, "FlexIO dma prep slave sg failed\n");
flexio_capture_cleanup_dma(fcam);
return -EINVAL;
}
if (dma_submit_error(dmaengine_submit(txdesc))) {
dev_err(fcam->dev, "submitting flexio dma failed\n");
flexio_capture_cleanup_dma(fcam);
return -EINVAL;
}
dma_async_issue_pending(chan);
return 0;
}
static irqreturn_t flexio_capture_vsync_irq(int irq, void *dev)
{
struct imx_flexio_capture_dev *fcam = dev;
struct flexio_capture_buffer *buf, *prev;
unsigned long flags;
dmaengine_terminate_all(fcam->hw.dma);
flexio_capture_clear_status_flag(fcam);
spin_lock_irqsave(&fcam->pipe.buf_lock, flags);
prev = fcam->pipe.active;
buf = list_first_entry_or_null(&fcam->pipe.pending,struct flexio_capture_buffer, list);
fcam->pipe.active = buf;
if (buf)
list_del_init(&buf->list);
spin_unlock_irqrestore(&fcam->pipe.buf_lock, flags);
if (prev)
vb2_buffer_done(&prev->v4l2_buf.vb2_buf, VB2_BUF_STATE_DONE);
flexio_capture_dma_submit(fcam);
return IRQ_HANDLED;
}
static int flexio_capture_prepare_dma(struct imx_flexio_capture_dev *fcam)
{
struct dma_slave_config cfg = { 0 };
cfg.src_addr = (phys_addr_t)(fcam->hw.src_addr + SHIFTBUF + FLEXIO_SHIFTER_START_IDX * 4);
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_32_BYTES;
cfg.src_maxburst = 1;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_32_BYTES;
cfg.dst_maxburst = 1;
cfg.direction = DMA_DEV_TO_MEM;
return dmaengine_slave_config(fcam->hw.dma, &cfg);
}
При этом prepare_dma вызывается только один раз(при start_streaming), и в нём нет указания dst_addr. Разве эту функцию не надо вызывать каждый раз по прерыванию VSYNC и явно указывать буфер &fcam->pipe.active->v4l2_buf.vb2_buf? Будет ли в такой реализации двойная буферизация?