/* * Allocate the buffers for the VRFB space. Data is copied from V4L2 * buffers to the VRFB buffers using the DMA engine. */ int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout, unsigned int *count, unsigned int startindex) { int i; bool yuv_mode; if (!is_rotation_enabled(vout)) return 0; /* If rotation is enabled, allocate memory for VRFB space also */ *count = *count > VRFB_NUM_BUFS ? VRFB_NUM_BUFS : *count; /* Allocate the VRFB buffers only if the buffers are not * allocated during init time. */ if (!vout->vrfb_static_allocation) if (omap_vout_allocate_vrfb_buffers(vout, count, startindex)) return -ENOMEM; if (vout->dss_mode == OMAP_DSS_COLOR_YUV2 || vout->dss_mode == OMAP_DSS_COLOR_UYVY) yuv_mode = true; else yuv_mode = false; for (i = 0; i < *count; i++) omap_vrfb_setup(&vout->vrfb_context[i], vout->smsshado_phy_addr[i], vout->pix.width, vout->pix.height, vout->bpp, yuv_mode); return 0; }
int omap_setup_vrfb_buffer(struct dss2_ovl_info *ovl_info) { int i = 0; int mode = ovl_info->cfg.color_mode; int got_vrfb_mapped_buf = 0; if (!have_vrfb_ctx) { pr_err("%s: No VRFB context available for setup\n", __func__); return 1; } for (i = 0; i < VRFB_NUM_SLOTS; i++) { if (ion_vrfb_t[i].ba == ovl_info->ba) { if (ion_vrfb_t[i].ismapped) { if (check_vrfb_params( &ion_vrfb_t[i].vrfb_context, ovl_info)) { got_vrfb_mapped_buf = 0; ion_vrfb_t[i].ismapped = 0; } else { ovl_info->ba = ion_vrfb_t[i]. vrfb_context. paddr[ovl_info->cfg.rotation] + omap_get_vrfb_offset( &ion_vrfb_t[i].vrfb_context, ovl_info->cfg.rotation); got_vrfb_mapped_buf = 1; } } break; } } if (!got_vrfb_mapped_buf) { omap_vrfb_setup(&ion_vrfb_t[i].vrfb_context, ovl_info->ba, ovl_info->cfg.crop.w, ovl_info->cfg.crop.h, get_bpp(mode), is_yuv_mode(mode)); ovl_info->ba = ion_vrfb_t[i]. vrfb_context.paddr[ovl_info->cfg.rotation] + omap_get_vrfb_offset( &ion_vrfb_t[i].vrfb_context, ovl_info->cfg.rotation); ion_vrfb_t[i].ismapped = 1; } if (ovl_info->cfg.rotation & 1) { #if 0 //[email protected] ti patch for HDMI ovl_info->cfg.win.w = (ovl_info->cfg.win.h * ovl_info->cfg.win.h) / ovl_info->cfg.win.w; #else ovl_info->cfg.win.w = (ovl_info->cfg.win.w * ovl_info->cfg.win.h) / ovl_info->cfg.win.h; #endif } ovl_info->cfg.stride = VRFB_LINE_LENGTH * 2; 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; }