Exemplo n.º 1
0
void omap_get_vrfb_buffer(__u32 paddr)
{
	int i = 0;
	int j = 0;

	if (have_vrfb_ctx >= VRFB_NUM_SLOTS)
		return;

	for (i = 0; i < VRFB_NUM_SLOTS; i++) {
		if (ion_vrfb_t[i].ba == 0) {
			if (omap_vrfb_request_ctx
				(&ion_vrfb_t[i].vrfb_context)) {
				pr_err("%s:VRFB allocation failed\n", __func__);
				for (j = 0; j < VRFB_NUM_SLOTS; j++)
					if (ion_vrfb_t[j].ba) {
						omap_vrfb_release_ctx(
						&ion_vrfb_t[j].vrfb_context);
						ion_vrfb_t[j].ba = 0;
						ion_vrfb_t[j].ismapped = 0;
						have_vrfb_ctx--;
				}
			return ;
			}
			ion_vrfb_t[i].ba = paddr;
			ion_vrfb_t[i].ismapped = 0;
			have_vrfb_ctx++;
			break;
		}
	}

	return;
}
Exemplo n.º 2
0
/*
 * Release the VRFB context once the module exits
 */
void omap_vout_release_vrfb(struct omap_vout_device *vout)
{
	int i;

	for (i = 0; i < VRFB_NUM_BUFS; i++)
		omap_vrfb_release_ctx(&vout->vrfb_context[i]);

	if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) {
		vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
		omap_free_dma(vout->vrfb_dma_tx.dma_ch);
	}
}
Exemplo n.º 3
0
int omap_vrfb_request_ctx(struct vrfb *vrfb)
{
	int rot;
	u32 paddr;
	u8 ctx;
	int r;

	DBG("request ctx\n");

	mutex_lock(&ctx_lock);

	for (ctx = 0; ctx < num_ctxs; ++ctx)
		if ((ctx_map & (1 << ctx)) == 0)
			break;

	if (ctx == num_ctxs) {
		pr_err("vrfb: no free contexts\n");
		r = -EBUSY;
		goto out;
	}

	DBG("found free ctx %d\n", ctx);

	set_bit(ctx, &ctx_map);

	memset(vrfb, 0, sizeof(*vrfb));

	vrfb->context = ctx;

	for (rot = 0; rot < 4; ++rot) {
		paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
		if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
			pr_err("vrfb: failed to reserve VRFB "
					"area for ctx %d, rotation %d\n",
					ctx, rot * 90);
			omap_vrfb_release_ctx(vrfb);
			r = -ENOMEM;
			goto out;
		}

		vrfb->paddr[rot] = paddr;

		DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]);
	}

	r = 0;
out:
	mutex_unlock(&ctx_lock);
	return r;
}
Exemplo n.º 4
0
static int omapvout_dss_release_vrfb(struct omapvout_device *vout)
{
	int rc = 0;
	int size;
	struct omapvout_dss_vrfb *vrfb;

	/* It is assumed that the caller has locked the vout mutex */

	vrfb = &vout->dss->vrfb;
	if (vrfb->req_status == DMA_CHAN_ALLOTED) {
		vrfb->req_status = DMA_CHAN_NOT_ALLOTED;
		omap_free_dma(vrfb->dma_ch);
		/* FIXME: de-init the wait queue? */

		size = vrfb->size;
		omapvout_mem_free(vrfb->phy_addr[0], vrfb->virt_addr[0], size);
		omapvout_mem_free(vrfb->phy_addr[1], vrfb->virt_addr[1], size);

		omap_vrfb_release_ctx(&vrfb->ctx[0]);
		omap_vrfb_release_ctx(&vrfb->ctx[1]);
	}

	return rc;
}
Exemplo n.º 5
0
void omap_free_vrfb_buffer(__u32 paddr)
{
	int j = 0;

	if (!have_vrfb_ctx)
		return;

	for (j = 0; j < VRFB_NUM_SLOTS; j++) {
		if (ion_vrfb_t[j].ba == paddr) {
			omap_vrfb_release_ctx(&ion_vrfb_t[j].vrfb_context);
			ion_vrfb_t[j].ba = 0;
			ion_vrfb_t[j].ismapped = 0;
			have_vrfb_ctx--;
			break;
		}
	}

}
Exemplo n.º 6
0
int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
			      bool static_vrfb_allocation)
{
	int ret = 0, i, j;
	struct omap_vout_device *vout;
	struct video_device *vfd;
	int image_width, image_height;
	int vrfb_num_bufs = VRFB_NUM_BUFS;
	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
	struct omap2video_device *vid_dev =
		container_of(v4l2_dev, struct omap2video_device, v4l2_dev);

	vout = vid_dev->vouts[vid_num];
	vfd = vout->vfd;

	for (i = 0; i < VRFB_NUM_BUFS; i++) {
		if (omap_vrfb_request_ctx(&vout->vrfb_context[i])) {
			dev_info(&pdev->dev, ": VRFB allocation failed\n");
			for (j = 0; j < i; j++)
				omap_vrfb_release_ctx(&vout->vrfb_context[j]);
			ret = -ENOMEM;
			goto free_buffers;
		}
	}

	/* Calculate VRFB memory size */
	/* allocate for worst case size */
	image_width = VID_MAX_WIDTH / TILE_SIZE;
	if (VID_MAX_WIDTH % TILE_SIZE)
		image_width++;

	image_width = image_width * TILE_SIZE;
	image_height = VID_MAX_HEIGHT / TILE_SIZE;

	if (VID_MAX_HEIGHT % TILE_SIZE)
		image_height++;

	image_height = image_height * TILE_SIZE;
	vout->smsshado_size = PAGE_ALIGN(image_width * image_height * 2 * 2);

	/*
	 * Request and Initialize DMA, for DMA based VRFB transfer
	 */
	vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE;
	vout->vrfb_dma_tx.dma_ch = -1;
	vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED;
	ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX",
			omap_vout_vrfb_dma_tx_callback,
			(void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
	if (ret < 0) {
		vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
		dev_info(&pdev->dev, ": failed to allocate DMA Channel for"
				" video%d\n", vfd->minor);
	}
	init_waitqueue_head(&vout->vrfb_dma_tx.wait);

	/* statically allocated the VRFB buffer is done through
	   commands line aruments */
	if (static_vrfb_allocation) {
		if (omap_vout_allocate_vrfb_buffers(vout, &vrfb_num_bufs, -1)) {
			ret =  -ENOMEM;
			goto release_vrfb_ctx;
		}
		vout->vrfb_static_allocation = 1;
	}
	return 0;

release_vrfb_ctx:
	for (j = 0; j < VRFB_NUM_BUFS; j++)
		omap_vrfb_release_ctx(&vout->vrfb_context[j]);
free_buffers:
	omap_vout_free_buffers(vout);

	return ret;
}
Exemplo n.º 7
0
static int omapvout_dss_acquire_vrfb(struct omapvout_device *vout)
{
	int rc = 0;
	int size;
	int w, h;
	int max_pixels;
	struct omapvout_dss_vrfb *vrfb;

	/* It is assumed that the caller has locked the vout mutex */

	vrfb = &vout->dss->vrfb;
	vrfb->dma_id = OMAP_DMA_NO_DEVICE;
	vrfb->dma_ch = -1;
	vrfb->req_status = DMA_CHAN_NOT_ALLOTED;
	vrfb->next = 0;

	rc = omap_vrfb_request_ctx(&vrfb->ctx[0]);
	if (rc != 0) {
		DBG("VRFB context allocation 0 failed %d\n", rc);
		goto failed_ctx0;
	}

	rc = omap_vrfb_request_ctx(&vrfb->ctx[1]);
	if (rc != 0) {
		DBG("VRFB context allocation 1 failed %d\n", rc);
		goto failed_ctx1;
	}

	/* Determine the VFRB buffer size by oversizing for the VRFB */
	w = vout->max_video_width;
	h = vout->max_video_height;
	max_pixels = w * h;
	w += 32; /* Oversize as typical for VRFB */
	h += 32;
	size = PAGE_ALIGN(w * h * (vout->max_video_buffer_size / max_pixels));
	vrfb->size = size;

	rc = omapvout_mem_alloc(size, &vrfb->phy_addr[0], &vrfb->virt_addr[0]);
	if (rc != 0) {
		DBG("VRFB buffer alloc 0 failed %d\n", rc);
		goto failed_mem0;
	}

	rc = omapvout_mem_alloc(size, &vrfb->phy_addr[1], &vrfb->virt_addr[1]);
	if (rc != 0) {
		DBG("VRFB buffer alloc 1 failed %d\n", rc);
		goto failed_mem1;
	}

	rc = omap_request_dma(vrfb->dma_id, "VRFB DMA",
				omapvout_dss_vrfb_dma_cb,
				(void *)vrfb,
				&vrfb->dma_ch);
	if (rc != 0) {
		printk(KERN_INFO "No VRFB DMA channel for %d\n", vout->id);
		goto failed_dma;
	}

	vrfb->req_status = DMA_CHAN_ALLOTED;
	init_waitqueue_head(&vrfb->wait);

	return rc;

failed_dma:
	omapvout_mem_free(vrfb->phy_addr[1], vrfb->virt_addr[1], size);
failed_mem1:
	omapvout_mem_free(vrfb->phy_addr[0], vrfb->virt_addr[0], size);
failed_mem0:
	omap_vrfb_release_ctx(&vrfb->ctx[1]);
failed_ctx1:
	omap_vrfb_release_ctx(&vrfb->ctx[0]);
failed_ctx0:
	return rc;
}