struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
struct mx3_camera_buffer *buf = to_mx3_vb(vb);
- struct dma_async_tx_descriptor *txd = buf->txd;
- struct idmac_channel *ichan = to_idmac_chan(txd->chan);
+ struct scatterlist *sg = &buf->sg;
+ struct dma_async_tx_descriptor *txd;
+ struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
struct idmac_video_param *video = &ichan->params.video;
- dma_cookie_t cookie;
- u32 fourcc = icd->current_fmt->host_fmt->fourcc;
+ const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt;
+ int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, host_fmt);
unsigned long flags;
- &ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
+ dma_cookie_t cookie;
+ size_t new_size;
+
+ BUG_ON(bytes_per_line <= 0);
+
+ new_size = bytes_per_line * icd->user_height;
+
+ if (vb2_plane_size(vb, 0) < new_size) {
+ dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n",
+ vb->v4l2_buf.index, vb2_plane_size(vb, 0), new_size);
+ goto error;
+ }
+
+ if (buf->state == CSI_BUF_NEEDS_INIT) {
+ sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0);
+ sg_dma_len(sg) = new_size;
+
+ txd = ichan->dma_chan.device->device_prep_slave_sg(
++ &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT);
+ if (!txd)
+ goto error;
+
+ txd->callback_param = txd;
+ txd->callback = mx3_cam_dma_done;
+
+ buf->state = CSI_BUF_PREPARED;
+ buf->txd = txd;
+ } else {
+ txd = buf->txd;
+ }
+
+ vb2_set_plane_payload(vb, 0, new_size);
/* This is the configuration of one sg-element */
- video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc);
+ video->out_pixel_fmt = fourcc_to_ipu_pix(host_fmt->fourcc);
if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) {
/*
struct scatterlist *sg;
unsigned int i;
enum dma_data_direction direction;
+ enum dma_transfer_direction slave_dirn;
unsigned int sglen;
+ u32 iflags;
+
+ data->error = -EINPROGRESS;
+
+ WARN_ON(host->data);
+ host->sg = NULL;
+ host->data = data;
+
+ iflags = ATMCI_DATA_ERROR_FLAGS;
/*
* We don't do DMA on "complex" transfers, i.e. with
if (!chan)
return -ENODEV;
- if (atmci_is_mci2())
- mci_writel(host, DMA, MCI_DMA_CHKSIZE(3) | MCI_DMAEN);
+ if (host->caps.has_dma)
+ atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(3) | ATMCI_DMAEN);
- if (data->flags & MMC_DATA_READ)
+ if (data->flags & MMC_DATA_READ) {
direction = DMA_FROM_DEVICE;
- else
+ slave_dirn = DMA_DEV_TO_MEM;
+ } else {
direction = DMA_TO_DEVICE;
+ slave_dirn = DMA_MEM_TO_DEV;
+ }
sglen = dma_map_sg(chan->device->dev, data->sg,
- data->sg_len, direction);
+ data->sg_len, direction);
desc = chan->device->device_prep_slave_sg(chan,
- data->sg, sglen, direction,
+ data->sg, sglen, slave_dirn,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc)
goto unmap_exit;