int omap_vout_prepare_vrfb(struct omap_vout_device *vout, struct videobuf_buffer *vb) { dma_addr_t dmabuf; struct vid_vrfb_dma *tx; enum dss_rotation rotation; u32 dest_frame_index = 0, src_element_index = 0; u32 dest_element_index = 0, src_frame_index = 0; u32 elem_count = 0, frame_count = 0, pixsize = 2; if (!is_rotation_enabled(vout)) return 0; dmabuf = vout->buf_phy_addr[vb->i]; /* If rotation is enabled, copy input buffer into VRFB * memory space using DMA. We are copying input buffer * into VRFB memory space of desired angle and DSS will * read image VRFB memory for 0 degree angle */ pixsize = vout->bpp * vout->vrfb_bpp; /* * DMA transfer in double index mode */ /* Frame index */ dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - (vout->pix.width * vout->bpp)) + 1; /* Source and destination parameters */ src_element_index = 0; src_frame_index = 0; dest_element_index = 1; /* Number of elements per frame */ elem_count = vout->pix.width * vout->bpp; frame_count = vout->pix.height; tx = &vout->vrfb_dma_tx; tx->tx_status = 0; omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32, (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT, tx->dev_id, 0x0); /* src_port required only for OMAP1 */ omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, dmabuf, src_element_index, src_frame_index); /*set dma source burst mode for VRFB */ omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); rotation = calc_rotation(vout); /* dest_port required only for OMAP1 */ omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, vout->vrfb_context[vb->i].paddr[0], dest_element_index, dest_frame_index); /*set dma dest burst mode for VRFB */ omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); omap_start_dma(tx->dma_ch); wait_event_interruptible_timeout(tx->wait, tx->tx_status == 1, VRFB_TX_TIMEOUT); if (tx->tx_status == 0) { omap_stop_dma(tx->dma_ch); return -EINVAL; } /* Store buffers physical address into an array. Addresses * from this array will be used to configure DSS */ vout->queued_buf_addr[vb->i] = (u8 *) vout->vrfb_context[vb->i].paddr[rotation]; return 0; }
static int omapvout_dss_perform_vrfb_dma(struct omapvout_device *vout, int buf_idx, bool vrfb_cfg) { int rc = 0; int rot = 0; struct omapvout_dss_vrfb *vrfb; u32 src_paddr; u32 dst_paddr; /* It is assumed that the caller has locked the vout mutex */ if (vout->dss->vrfb.req_status != DMA_CHAN_ALLOTED) return -EINVAL; vrfb = &vout->dss->vrfb; if (vrfb_cfg) { enum omap_color_mode dss_fmt; int bytespp; int w, h; u32 fmt = vout->pix.pixelformat; w = vout->crop.width; h = vout->crop.height; dss_fmt = omapvout_dss_color_mode(vout->pix.pixelformat); omap_vrfb_setup(&vrfb->ctx[0], vrfb->phy_addr[0], w, h, dss_fmt, vout->rotation); omap_vrfb_setup(&vrfb->ctx[1], vrfb->phy_addr[1], w, h, dss_fmt, vout->rotation); bytespp = omapvout_dss_format_bytespp(vout->pix.pixelformat); vrfb->en = (w * bytespp) / 4; /* 32 bit ES */ vrfb->fn = h; vrfb->dst_ei = 1; if (fmt == V4L2_PIX_FMT_YUYV || fmt == V4L2_PIX_FMT_UYVY) { vrfb->dst_fi = (OMAP_VRFB_LINE_LEN * bytespp * 2) - (vrfb->en * 4) + 1; } else { vrfb->dst_fi = (OMAP_VRFB_LINE_LEN * bytespp) - (vrfb->en * 4) + 1; } } switch (vout->rotation) { case 1: rot = 3; break; case 3: rot = 1; break; default: rot = vout->rotation; break; } src_paddr = vout->queue.bufs[buf_idx]->baddr; dst_paddr = vrfb->ctx[vrfb->next].paddr[rot]; omap_set_dma_transfer_params(vrfb->dma_ch, OMAP_DMA_DATA_TYPE_S32, vrfb->en, vrfb->fn, OMAP_DMA_SYNC_ELEMENT, vrfb->dma_id, 0x0); omap_set_dma_src_params(vrfb->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, src_paddr, 0, 0); omap_set_dma_src_burst_mode(vrfb->dma_ch, OMAP_DMA_DATA_BURST_16); omap_set_dma_dest_params(vrfb->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, dst_paddr, vrfb->dst_ei, vrfb->dst_fi); omap_set_dma_dest_burst_mode(vrfb->dma_ch, OMAP_DMA_DATA_BURST_16); omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); vrfb->dma_complete = false; omap_start_dma(vrfb->dma_ch); wait_event_interruptible_timeout(vrfb->wait, vrfb->dma_complete, VRFB_TX_TIMEOUT); if (!vrfb->dma_complete) { DBG("VRFB DMA timeout\n"); omap_stop_dma(vrfb->dma_ch); return -EINVAL; } return rc; }