Example #1
0
/* apply mode to plane pipe */
void xilinx_drm_plane_commit(struct drm_plane *base_plane)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct dma_async_tx_descriptor *desc;
	enum dma_ctrl_flags flags;
	unsigned int i;

	DRM_DEBUG_KMS("plane->id: %d\n", plane->id);

	for (i = 0; i < MAX_NUM_SUB_PLANES; i++) {
		struct xilinx_drm_plane_dma *dma = &plane->dma[i];

		if (dma->chan && dma->is_active) {
			flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
			desc = dmaengine_prep_interleaved_dma(dma->chan,
							      &dma->xt,
							      flags);
			if (!desc) {
				DRM_ERROR("failed to prepare DMA descriptor\n");
				return;
			}

			dmaengine_submit(desc);

			dma_async_issue_pending(dma->chan);
		}
	}
}
/* apply mode to plane pipe */
void xilinx_drm_plane_commit(struct drm_plane *base_plane)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct dma_async_tx_descriptor *desc;
	enum dma_ctrl_flags flags;

	DRM_DEBUG_KMS("plane->id: %d\n", plane->id);

	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
	desc = dmaengine_prep_interleaved_dma(plane->dma.chan, &plane->dma.xt,
					      flags);
	if (!desc) {
		DRM_ERROR("failed to prepare DMA descriptor\n");
		return;
	}

	/* submit dma desc */
	dmaengine_submit(desc);

	/* start dma with new mode */
	dma_async_issue_pending(plane->dma.chan);
}
static int vdmafb_setupfb(struct vdmafb_dev *fbdev)
{
	struct fb_var_screeninfo *var = &fbdev->info.var;
	struct dma_async_tx_descriptor *desc;
	struct dma_interleaved_template *dma_template = fbdev->dma_template;
	struct xilinx_vdma_config vdma_config;
	int hsize = var->xres * 4;
	u32 frame;
	int ret;

	/* Disable display */
	vdmafb_writereg(fbdev, VDMAFB_CONTROL, 0);

	dmaengine_terminate_all(fbdev->dma);

	/* Setup VDMA address etc */
	memset(&vdma_config, 0, sizeof(vdma_config));
	vdma_config.park = 1;
	vdma_config.coalesc = 255; /* Reduces unused interrupts */
	xilinx_vdma_channel_set_config(fbdev->dma, &vdma_config);

       /*
        * Interleaved DMA:
        * Each interleaved frame is a row (hsize) implemented in ONE
        * chunk (sgl has len 1).
        * The number of interleaved frames is the number of rows (vsize).
        * The icg in used to pack data to the HW, so that the buffer len
        * is fb->piches[0], but the actual size for the hw is somewhat less
        */
       dma_template->dir = DMA_MEM_TO_DEV;
       dma_template->src_start = fbdev->fb_phys;
       /* sgl list have just one entry (each interleaved frame have 1 chunk) */
       dma_template->frame_size = 1;
       /* the number of interleaved frame, each has the size specified in sgl */
       dma_template->numf = var->yres;
       dma_template->src_sgl = 1;
       dma_template->src_inc = 1;
       /* vdma IP does not provide any addr to the hdmi IP */
       dma_template->dst_inc = 0;
       dma_template->dst_sgl = 0;
       /* horizontal size */
       dma_template->sgl[0].size = hsize;
       /* the vdma driver seems to look at icg, and not src_icg */
       dma_template->sgl[0].icg = 0; /*  stride - hsize */

	for (frame = 0; frame < fbdev->frames; ++frame) {
		desc = dmaengine_prep_interleaved_dma(fbdev->dma, dma_template, 0);
		if (!desc) {
			pr_err("Failed to prepare DMA descriptor\n");
			return -ENOMEM;
		}
		dmaengine_submit(desc);
	}
	dma_async_issue_pending(fbdev->dma);

	/* Configure IP via registers */
	vdmafb_writereg(fbdev, VDMAFB_HORIZONTAL_TOTAL,
		var->hsync_len + var->left_margin + var->xres + var->right_margin);
	vdmafb_writereg(fbdev, VDMAFB_HORIZONTAL_SYNC, var->hsync_len);
	vdmafb_writereg(fbdev, VDMAFB_HORIZONTAL_FRONT_PORCH, var->left_margin);
	vdmafb_writereg(fbdev, VDMAFB_HORIZONTAL_WIDTH, var->xres);
	vdmafb_writereg(fbdev, VDMAFB_HORIZONTAL_BACK_PORCH, var->right_margin);
	vdmafb_writereg(fbdev, VDMAFB_HORIZONTAL_POLARITY, 0); /* TODO */
	vdmafb_writereg(fbdev, VDMAFB_VERTICAL_TOTAL,
		var->vsync_len + var->upper_margin + var->yres + var->lower_margin);
	vdmafb_writereg(fbdev, VDMAFB_VERTICAL_SYNC, var->vsync_len);
	vdmafb_writereg(fbdev, VDMAFB_VERTICAL_FRONT_PORCH, var->upper_margin);
	vdmafb_writereg(fbdev, VDMAFB_VERTICAL_HEIGHT, var->yres);
	vdmafb_writereg(fbdev, VDMAFB_VERTICAL_BACK_PORCH, var->lower_margin);
	vdmafb_writereg(fbdev, VDMAFB_VERTICAL_POLARITY, 0);
	/* Enable output */
	vdmafb_writereg(fbdev, VDMAFB_CONTROL, VDMAFB_CONTROL_ENABLE);

	/* Set brightness */

	vdmafb_writereg(fbdev, VDMAFB_BACKLIGHT_CONTROL, 1);
	vdmafb_writereg(fbdev, VDMAFB_BACKLIGHT_LEVEL_1K, 800);

	return 0;
}