static void mx3fb_dma_done(void *arg) { struct idmac_tx_desc *tx_desc = to_tx_desc(arg); struct dma_chan *chan = tx_desc->txd.chan; struct idmac_channel *ichannel = to_idmac_chan(chan); struct mx3fb_data *mx3fb = ichannel->client; struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq); /* We only need one interrupt, it will be re-enabled as needed */ disable_irq_nosync(ichannel->eof_irq); complete(&mx3_fbi->flip_cmpl); }
static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) { dma_cap_mask_t mask; struct dma_chan *chan; struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; /* We have to use IDMAC_IC_7 for Bayer / generic data */ struct dma_chan_request rq = {.mx3_cam = mx3_cam, .id = IDMAC_IC_7}; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_PRIVATE, mask); chan = dma_request_channel(mask, chan_filter, &rq); if (!chan) return -EBUSY; *ichan = to_idmac_chan(chan); (*ichan)->client = mx3_cam; return 0; }
/* Called from the IPU IDMAC ISR */ static void mx3_cam_dma_done(void *arg) { struct idmac_tx_desc *desc = to_tx_desc(arg); struct dma_chan *chan = desc->txd.chan; struct idmac_channel *ichannel = to_idmac_chan(chan); struct mx3_camera_dev *mx3_cam = ichannel->client; dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n", desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0); spin_lock(&mx3_cam->lock); if (mx3_cam->active) { struct vb2_buffer *vb = &mx3_cam->active->vb; struct mx3_camera_buffer *buf = to_mx3_vb(vb); list_del_init(&buf->queue); do_gettimeofday(&vb->v4l2_buf.timestamp); vb->v4l2_buf.field = mx3_cam->field; vb->v4l2_buf.sequence = mx3_cam->sequence++; vb2_buffer_done(vb, VB2_BUF_STATE_DONE); } if (list_empty(&mx3_cam->capture)) { mx3_cam->active = NULL; spin_unlock(&mx3_cam->lock); /* * stop capture - without further buffers IPU_CHA_BUF0_RDY will * not get updated */ return; } mx3_cam->active = list_entry(mx3_cam->capture.next, struct mx3_camera_buffer, queue); spin_unlock(&mx3_cam->lock); }
static void mx3_videobuf_queue(struct vb2_buffer *vb) { struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.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 idmac_video_param *video = &ichan->params.video; dma_cookie_t cookie; u32 fourcc = icd->current_fmt->host_fmt->fourcc; unsigned long flags; /* This is the configuration of one sg-element */ video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) { /* * If the IPU DMA channel is configured to transport * generic 8-bit data, we have to set up correctly the * geometry parameters upon the current pixel format. * So, since the DMA horizontal parameters are expressed * in bytes not pixels, convert these in the right unit. */ int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); BUG_ON(bytes_per_line <= 0); video->out_width = bytes_per_line; video->out_height = icd->user_height; video->out_stride = bytes_per_line; } else { /* * For IPU known formats the pixel unit will be managed * successfully by the IPU code */ video->out_width = icd->user_width; video->out_height = icd->user_height; video->out_stride = icd->user_width; } #ifdef DEBUG /* helps to see what DMA actually has written */ if (vb2_plane_vaddr(vb, 0)) memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0)); #endif spin_lock_irqsave(&mx3_cam->lock, flags); list_add_tail(&buf->queue, &mx3_cam->capture); if (!mx3_cam->active) mx3_cam->active = buf; spin_unlock_irq(&mx3_cam->lock); cookie = txd->tx_submit(txd); dev_dbg(icd->dev.parent, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg)); if (cookie >= 0) return; spin_lock_irq(&mx3_cam->lock); /* Submit error */ list_del_init(&buf->queue); if (mx3_cam->active == buf) mx3_cam->active = NULL; spin_unlock_irqrestore(&mx3_cam->lock, flags); vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); }