Загрузка данных


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? Будет ли в такой реализации двойная буферизация?