예제 #1
0
/* mode set a plane */
int xilinx_drm_plane_mode_set(struct drm_plane *base_plane,
			      struct drm_framebuffer *fb,
			      int crtc_x, int crtc_y,
			      unsigned int crtc_w, unsigned int crtc_h,
			      uint32_t src_x, uint32_t src_y,
			      uint32_t src_w, uint32_t src_h)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct drm_gem_cma_object *obj;
	size_t offset;
	unsigned int hsub, vsub, i;

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

	if (fb->pixel_format != plane->format) {
		DRM_ERROR("unsupported pixel format %08x\n", fb->pixel_format);
		return -EINVAL;
	}

	/* configure cresample */
	if (plane->cresample)
		xilinx_cresample_configure(plane->cresample, crtc_w, crtc_h);

	/* configure rgb2yuv */
	if (plane->rgb2yuv)
		xilinx_rgb2yuv_configure(plane->rgb2yuv, crtc_w, crtc_h);

	DRM_DEBUG_KMS("h: %d(%d), v: %d(%d)\n",
			src_w, crtc_x, src_h, crtc_y);
	DRM_DEBUG_KMS("bpp: %d\n", fb->bits_per_pixel / 8);

	hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
	vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);

	for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
		unsigned int width = src_w / (i ? hsub : 1);
		unsigned int height = src_h / (i ? vsub : 1);
		unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, i);

		obj = xilinx_drm_fb_get_gem_obj(fb, i);
		if (!obj) {
			DRM_ERROR("failed to get a gem obj for fb\n");
			return -EINVAL;
		}

		plane->dma[i].xt.numf = height;
		plane->dma[i].sgl[0].size = width * cpp;
		plane->dma[i].sgl[0].icg = fb->pitches[i] -
					   plane->dma[i].sgl[0].size;
		offset = src_x * cpp + src_y * fb->pitches[i];
		offset += fb->offsets[i];
		plane->dma[i].xt.src_start = obj->paddr + offset;
		plane->dma[i].xt.frame_size = 1;
		plane->dma[i].xt.dir = DMA_MEM_TO_DEV;
		plane->dma[i].xt.src_sgl = true;
		plane->dma[i].xt.dst_sgl = false;
		plane->dma[i].is_active = true;
	}

	for (; i < MAX_NUM_SUB_PLANES; i++)
		plane->dma[i].is_active = false;

	/* set OSD dimensions */
	if (plane->manager->osd) {
		xilinx_osd_disable_rue(plane->manager->osd);

		xilinx_osd_layer_set_dimension(plane->osd_layer, crtc_x, crtc_y,
					       src_w, src_h);

		xilinx_osd_enable_rue(plane->manager->osd);
	}

	if (plane->manager->dp_sub) {
		int ret;

		ret = xilinx_drm_dp_sub_layer_check_size(plane->manager->dp_sub,
							 plane->dp_layer,
							 src_w, src_h);
		if (ret)
			return ret;
	}

	return 0;
}
예제 #2
0
/* mode set a plane */
int xilinx_drm_plane_mode_set(struct drm_plane *base_plane,
			      struct drm_framebuffer *fb,
			      int crtc_x, int crtc_y,
			      unsigned int crtc_w, unsigned int crtc_h,
			      uint32_t src_x, uint32_t src_y,
			      uint32_t src_w, uint32_t src_h)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct drm_gem_cma_object *obj;
	size_t offset;

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

	if (fb->pixel_format != plane->format) {
		DRM_ERROR("unsupported pixel format %08x\n", fb->pixel_format);
		return -EINVAL;
	}

	/* configure cresample */
	if (plane->cresample)
		xilinx_cresample_configure(plane->cresample, crtc_w, crtc_h);

	/* configure rgb2yuv */
	if (plane->rgb2yuv)
		xilinx_rgb2yuv_configure(plane->rgb2yuv, crtc_w, crtc_h);

	obj = drm_fb_cma_get_gem_obj(fb, 0);
	if (!obj) {
		DRM_ERROR("failed to get a gem obj for fb\n");
		return -EINVAL;
	}

	DRM_DEBUG_KMS("h: %d(%d), v: %d(%d), paddr: %p\n",
		      src_w, crtc_x, src_h, crtc_y, (void *)obj->paddr);
	DRM_DEBUG_KMS("bpp: %d\n", fb->bits_per_pixel / 8);

	/* configure dma desc */
	plane->dma.xt.numf = src_h;
	plane->dma.sgl[0].size = src_w * fb->bits_per_pixel / 8;
	plane->dma.sgl[0].icg = fb->pitches[0] - plane->dma.sgl[0].size;
	offset = src_x * fb->bits_per_pixel / 8 + src_y * fb->pitches[0];
	plane->dma.xt.src_start = obj->paddr + offset;
	plane->dma.xt.frame_size = 1;
	plane->dma.xt.dir = DMA_MEM_TO_DEV;
	plane->dma.xt.src_sgl = true;
	plane->dma.xt.dst_sgl = false;

	/* set OSD dimensions */
	if (plane->manager->osd) {
		xilinx_osd_disable_rue(plane->manager->osd);

		/* if a plane is private, it's for crtc */
		if (plane->priv)
			xilinx_osd_set_dimension(plane->manager->osd,
						 crtc_w, crtc_h);

		xilinx_osd_layer_set_dimension(plane->osd_layer, crtc_x, crtc_y,
					       src_w, src_h);

		xilinx_osd_enable_rue(plane->manager->osd);
	}

	return 0;
}
예제 #3
0
/* set new mode in crtc pipe */
static int xilinx_drm_crtc_mode_set(struct drm_crtc *base_crtc,
				    struct drm_display_mode *mode,
				    struct drm_display_mode *adjusted_mode,
				    int x, int y,
				    struct drm_framebuffer *old_fb)
{
	struct xilinx_drm_crtc *crtc = to_xilinx_crtc(base_crtc);
	struct videomode vm;
	long diff;
	int ret;

	/* set pixel clock */
	ret = clk_set_rate(crtc->pixel_clock, adjusted_mode->clock * 1000);
	if (ret) {
		DRM_ERROR("failed to set a pixel clock\n");
		return ret;
	}

	diff = clk_get_rate(crtc->pixel_clock) - adjusted_mode->clock * 1000;
	if (abs(diff) > (adjusted_mode->clock * 1000) / 20)
		DRM_INFO("actual pixel clock rate(%d) is off by %ld\n",
				adjusted_mode->clock, diff);

	/* set video timing */
	vm.hactive = adjusted_mode->hdisplay;
	vm.hfront_porch = adjusted_mode->hsync_start - adjusted_mode->hdisplay;
	vm.hback_porch = adjusted_mode->htotal - adjusted_mode->hsync_end;
	vm.hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;

	vm.vactive = adjusted_mode->vdisplay;
	vm.vfront_porch = adjusted_mode->vsync_start - adjusted_mode->vdisplay;
	vm.vback_porch = adjusted_mode->vtotal - adjusted_mode->vsync_end;
	vm.vsync_len = adjusted_mode->vsync_end - adjusted_mode->vsync_start;

	xilinx_vtc_config_sig(crtc->vtc, &vm);

	/* configure cresample and rgb2yuv */
	if (crtc->cresample)
		xilinx_cresample_configure(crtc->cresample,
					   adjusted_mode->hdisplay,
					   adjusted_mode->vdisplay);
	if (crtc->rgb2yuv)
		xilinx_rgb2yuv_configure(crtc->rgb2yuv,
					 adjusted_mode->hdisplay,
					 adjusted_mode->vdisplay);

	/* configure a plane: vdma and osd layer */
	ret = xilinx_drm_plane_mode_set(crtc->priv_plane,
					base_crtc->fb, 0, 0,
					adjusted_mode->hdisplay,
					adjusted_mode->vdisplay,
					x, y,
					adjusted_mode->hdisplay,
					adjusted_mode->vdisplay);
	if (ret) {
		DRM_ERROR("failed to mode set a plane\n");
		return ret;
	}

	return 0;
}
예제 #4
0
/* mode set a plane */
int xilinx_drm_plane_mode_set(struct drm_plane *base_plane,
			      struct drm_framebuffer *fb,
			      int crtc_x, int crtc_y,
			      unsigned int crtc_w, unsigned int crtc_h,
			      uint32_t src_x, uint32_t src_y,
			      uint32_t src_w, uint32_t src_h)
{
	struct xilinx_drm_plane *plane = to_xilinx_plane(base_plane);
	struct drm_gem_cma_object *obj;

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

	if (fb->pixel_format != plane->format) {
		DRM_ERROR("unsupported pixel format %08x\n", fb->pixel_format);
		return -EINVAL;
	}

	/* configure cresample */
	if (plane->cresample)
		xilinx_cresample_configure(plane->cresample, crtc_w, crtc_h);

	/* configure rgb2yuv */
	if (plane->rgb2yuv)
		xilinx_rgb2yuv_configure(plane->rgb2yuv, crtc_w, crtc_h);

	obj = drm_fb_cma_get_gem_obj(fb, 0);
	if (!obj) {
		DRM_ERROR("failed to get a gem obj for fb\n");
		return -EINVAL;
	}

	plane->x = src_x;
	plane->y = src_y;
	plane->bpp = fb->bits_per_pixel / 8;
	plane->paddr = obj->paddr;

	DRM_DEBUG_KMS("h: %d(%d), v: %d(%d), paddr: %p\n",
		      src_w, crtc_x, src_h, crtc_y, (void *)obj->paddr);
	DRM_DEBUG_KMS("bpp: %d\n", plane->bpp);

	/* configure vdma desc */
	plane->vdma.dma_config.hsize = src_w * plane->bpp;
	plane->vdma.dma_config.vsize = src_h;
	plane->vdma.dma_config.stride = fb->pitches[0];
	plane->vdma.dma_config.park = 1;
	plane->vdma.dma_config.park_frm = 0;

	dmaengine_device_control(plane->vdma.chan, DMA_SLAVE_CONFIG,
				 (unsigned long)&plane->vdma.dma_config);

	/* set OSD dimensions */
	if (plane->manager->osd) {
		xilinx_osd_disable_rue(plane->manager->osd);

		/* if a plane is private, it's for crtc */
		if (plane->priv)
			xilinx_osd_set_dimension(plane->manager->osd,
						 crtc_w, crtc_h);

		xilinx_osd_layer_set_dimension(plane->osd_layer, crtc_x, crtc_y,
					       src_w, src_h);

		xilinx_osd_enable_rue(plane->manager->osd);
	}

	return 0;
}