Ejemplo n.º 1
0
static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
					int x, int y)
{
	struct drm_crtc *crtc = &scrtc->crtc;
	struct drm_framebuffer *fb = crtc->primary->fb;
	struct shmob_drm_device *sdev = crtc->dev->dev_private;
	struct drm_gem_cma_object *gem;
	unsigned int bpp;

	bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp;
	gem = drm_fb_cma_get_gem_obj(fb, 0);
	scrtc->dma[0] = gem->paddr + fb->offsets[0]
		      + y * fb->pitches[0] + x * bpp / 8;

	if (scrtc->format->yuv) {
		bpp = scrtc->format->bpp - 8;
		gem = drm_fb_cma_get_gem_obj(fb, 1);
		scrtc->dma[1] = gem->paddr + fb->offsets[1]
			      + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
			      + x * (bpp == 16 ? 2 : 1);
	}

	if (scrtc->cache)
		sh_mobile_meram_cache_update(sdev->meram, scrtc->cache,
					     scrtc->dma[0], scrtc->dma[1],
					     &scrtc->dma[0], &scrtc->dma[1]);
}
Ejemplo n.º 2
0
static void hdlcd_plane_atomic_update(struct drm_plane *plane,
				      struct drm_plane_state *state)
{
	struct drm_framebuffer *fb = plane->state->fb;
	struct hdlcd_drm_private *hdlcd;
	struct drm_gem_cma_object *gem;
	u32 src_x, src_y, dest_h;
	dma_addr_t scanout_start;

	if (!fb)
		return;

	src_x = plane->state->src.x1 >> 16;
	src_y = plane->state->src.y1 >> 16;
	dest_h = drm_rect_height(&plane->state->dst);
	gem = drm_fb_cma_get_gem_obj(fb, 0);

	scanout_start = gem->paddr + fb->offsets[0] +
			src_y * fb->pitches[0] +
			src_x *	fb->format->cpp[0];

	hdlcd = plane->dev->dev_private;
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]);
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, fb->pitches[0]);
	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
	hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
}
Ejemplo n.º 3
0
static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb,
			 u32 ch, u32 y, u32 in_h, u32 fmt)
{
	struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
	struct drm_format_name_buf format_name;
	u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
	u32 stride = fb->pitches[0];
	u32 addr = (u32)obj->paddr + y * stride;

	DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n",
			 ch + 1, y, in_h, stride, (u32)obj->paddr);
	DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n",
			 addr, fb->width, fb->height, fmt,
			 drm_get_format_name(fb->pixel_format, &format_name));

	/* get reg offset */
	reg_ctrl = RD_CH_CTRL(ch);
	reg_addr = RD_CH_ADDR(ch);
	reg_size = RD_CH_SIZE(ch);
	reg_stride = RD_CH_STRIDE(ch);
	reg_space = RD_CH_SPACE(ch);
	reg_en = RD_CH_EN(ch);

	/*
	 * TODO: set rotation
	 */
	writel((fmt << 16) & 0x1f0000, base + reg_ctrl);
	writel(addr, base + reg_addr);
	writel((in_h << 16) | stride, base + reg_size);
	writel(stride, base + reg_stride);
	writel(in_h * stride, base + reg_space);
	writel(ADE_ENABLE, base + reg_en);
	ade_update_reload_bit(base, RDMA_OFST + ch, 0);
}
Ejemplo n.º 4
0
static int ipu_drm_set_base(struct drm_crtc *crtc, int x, int y)
{
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct drm_gem_cma_object *cma_obj;
	struct drm_framebuffer *fb = crtc->fb;
	unsigned long phys;

	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
	if (!cma_obj) {
		DRM_LOG_KMS("entry is null.\n");
		return -EFAULT;
	}

	phys = cma_obj->paddr;
	phys += x * (fb->bits_per_pixel >> 3);
	phys += y * fb->pitches[0];

	dev_dbg(ipu_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys);
	dev_dbg(ipu_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y);

	ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]);
	ipu_cpmem_set_buffer(ipu_get_cpmem(ipu_crtc->ipu_ch),
			  0, phys);

	return 0;
}
Ejemplo n.º 5
0
static int
malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
			       struct drm_crtc_state *crtc_state,
			       struct drm_connector_state *conn_state)
{
	struct malidp_mw_connector_state *mw_state = to_mw_state(conn_state);
	struct malidp_drm *malidp = encoder->dev->dev_private;
	struct drm_framebuffer *fb;
	int i, n_planes;

	if (!conn_state->writeback_job || !conn_state->writeback_job->fb)
		return 0;

	fb = conn_state->writeback_job->fb;
	if ((fb->width != crtc_state->mode.hdisplay) ||
	    (fb->height != crtc_state->mode.vdisplay)) {
		DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n",
				fb->width, fb->height);
		return -EINVAL;
	}

	if (fb->modifier) {
		DRM_DEBUG_KMS("Writeback framebuffer does not support modifiers\n");
		return -EINVAL;
	}

	mw_state->format =
		malidp_hw_get_format_id(&malidp->dev->hw->map, SE_MEMWRITE,
					fb->format->format, !!fb->modifier);
	if (mw_state->format == MALIDP_INVALID_FORMAT_ID) {
		struct drm_format_name_buf format_name;

		DRM_DEBUG_KMS("Invalid pixel format %s\n",
			      drm_get_format_name(fb->format->format,
						  &format_name));
		return -EINVAL;
	}

	n_planes = drm_format_num_planes(fb->format->format);
	for (i = 0; i < n_planes; i++) {
		struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i);
		/* memory write buffers are never rotated */
		u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0);

		if (fb->pitches[i] & (alignment - 1)) {
			DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
				      fb->pitches[i], i);
			return -EINVAL;
		}
		mw_state->pitches[i] = fb->pitches[i];
		mw_state->addrs[i] = obj->paddr + fb->offsets[i];
	}
	mw_state->n_planes = n_planes;

	if (fb->format->is_yuv)
		mw_state->rgb2yuv_coeffs = rgb2yuv_coeffs_bt709_limited;

	return 0;
}
Ejemplo n.º 6
0
static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
					struct drm_plane_state *state)
{
	struct arcpgu_drm_private *arcpgu;
	struct drm_gem_cma_object *gem;

	if (!plane->state->crtc || !plane->state->fb)
		return;

	arcpgu = crtc_to_arcpgu_priv(plane->state->crtc);
	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
}
Ejemplo n.º 7
0
static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
					    struct drm_plane_state *old_state)

{
	struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
	struct drm_plane_state *state = plane->state;
	struct drm_framebuffer *fb = plane->state->fb;
	struct drm_gem_cma_object *gem;
	unsigned int alpha, bpp;
	int index, ret;

	if (!fb)
		return;

	index = fsl_dcu_drm_plane_index(plane);
	if (index < 0)
		return;

	gem = drm_fb_cma_get_gem_obj(fb, 0);

	switch (fb->pixel_format) {
	case DRM_FORMAT_RGB565:
		bpp = FSL_DCU_RGB565;
		alpha = 0xff;
		break;
	case DRM_FORMAT_RGB888:
		bpp = FSL_DCU_RGB888;
		alpha = 0xff;
		break;
	case DRM_FORMAT_ARGB8888:
		bpp = FSL_DCU_ARGB8888;
		alpha = 0xff;
		break;
	case DRM_FORMAT_BGRA4444:
		bpp = FSL_DCU_ARGB4444;
		alpha = 0xff;
		break;
	case DRM_FORMAT_ARGB1555:
		bpp = FSL_DCU_ARGB1555;
		alpha = 0xff;
		break;
	case DRM_FORMAT_YUV422:
		bpp = FSL_DCU_YUV422;
		alpha = 0xff;
		break;
	default:
		return;
	}

	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 1),
			   DCU_LAYER_HEIGHT(state->crtc_h) |
			   DCU_LAYER_WIDTH(state->crtc_w));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 2),
			   DCU_LAYER_POSY(state->crtc_y) |
			   DCU_LAYER_POSX(state->crtc_x));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap,
			   DCU_CTRLDESCLN(index, 3), gem->paddr);
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
			   DCU_LAYER_EN |
			   DCU_LAYER_TRANS(alpha) |
			   DCU_LAYER_BPP(bpp) |
			   DCU_LAYER_AB(0));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 5),
			   DCU_LAYER_CKMAX_R(0xFF) |
			   DCU_LAYER_CKMAX_G(0xFF) |
			   DCU_LAYER_CKMAX_B(0xFF));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 6),
			   DCU_LAYER_CKMIN_R(0) |
			   DCU_LAYER_CKMIN_G(0) |
			   DCU_LAYER_CKMIN_B(0));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 7), 0);
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 8),
			   DCU_LAYER_FG_FCOLOR(0));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 9),
			   DCU_LAYER_BG_BCOLOR(0));
	if (ret)
		goto set_failed;
	if (!strcmp(fsl_dev->soc->name, "ls1021a")) {
		ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 10),
				   DCU_LAYER_POST_SKIP(0) |
				   DCU_LAYER_PRE_SKIP(0));
		if (ret)
			goto set_failed;
	}
	ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
				 DCU_MODE_DCU_MODE_MASK,
				 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap,
			   DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
	if (ret)
		goto set_failed;
	return;

set_failed:
	dev_err(fsl_dev->dev, "set DCU register failed\n");
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
0
static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
				    struct drm_plane_state *oldstate)
{
	struct drm_plane_state *state = drm_plane->state;
	struct sti_plane *plane = to_sti_plane(drm_plane);
	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
	struct drm_crtc *crtc = state->crtc;
	struct drm_framebuffer *fb = state->fb;
	struct drm_display_mode *mode;
	int dst_x, dst_y, dst_w, dst_h;
	int src_x, src_y, src_w, src_h;
	struct drm_gem_cma_object *cma_obj;
	struct sti_hqvdp_cmd *cmd;
	int scale_h, scale_v;
	int cmd_offset;

	if (!crtc || !fb)
		return;

	mode = &crtc->mode;
	dst_x = state->crtc_x;
	dst_y = state->crtc_y;
	dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
	dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
	/* src_x are in 16.16 format */
	src_x = state->src_x >> 16;
	src_y = state->src_y >> 16;
	src_w = state->src_w >> 16;
	src_h = state->src_h >> 16;

	cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
	if (cmd_offset == -1) {
		DRM_DEBUG_DRIVER("Warning: no cmd, will skip frame\n");
		return;
	}
	cmd = hqvdp->hqvdp_cmd + cmd_offset;

	/* Static parameters, defaulting to progressive mode */
	cmd->top.config = TOP_CONFIG_PROGRESSIVE;
	cmd->top.mem_format = TOP_MEM_FORMAT_DFLT;
	cmd->hvsrc.param_ctrl = HVSRC_PARAM_CTRL_DFLT;
	cmd->csdi.config = CSDI_CONFIG_PROG;

	/* VC1RE, FMD bypassed : keep everything set to 0
	 * IQI/P2I bypassed */
	cmd->iqi.config = IQI_CONFIG_DFLT;
	cmd->iqi.con_bri = IQI_CON_BRI_DFLT;
	cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT;
	cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;

	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);

	DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
			 (char *)&fb->pixel_format,
			 (unsigned long)cma_obj->paddr);

	/* Buffer planes address */
	cmd->top.current_luma = (u32)cma_obj->paddr + fb->offsets[0];
	cmd->top.current_chroma = (u32)cma_obj->paddr + fb->offsets[1];

	/* Pitches */
	cmd->top.luma_processed_pitch = fb->pitches[0];
	cmd->top.luma_src_pitch = fb->pitches[0];
	cmd->top.chroma_processed_pitch = fb->pitches[1];
	cmd->top.chroma_src_pitch = fb->pitches[1];

	/* Input / output size
	 * Align to upper even value */
	dst_w = ALIGN(dst_w, 2);
	dst_h = ALIGN(dst_h, 2);

	cmd->top.input_viewport_size = src_h << 16 | src_w;
	cmd->top.input_frame_size = src_h << 16 | src_w;
	cmd->hvsrc.output_picture_size = dst_h << 16 | dst_w;
	cmd->top.input_viewport_ori = src_y << 16 | src_x;

	/* Handle interlaced */
	if (fb->flags & DRM_MODE_FB_INTERLACED) {
		/* Top field to display */
		cmd->top.config = TOP_CONFIG_INTER_TOP;

		/* Update pitches and vert size */
		cmd->top.input_frame_size = (src_h / 2) << 16 | src_w;
		cmd->top.luma_processed_pitch *= 2;
		cmd->top.luma_src_pitch *= 2;
		cmd->top.chroma_processed_pitch *= 2;
		cmd->top.chroma_src_pitch *= 2;

		/* Enable directional deinterlacing processing */
		cmd->csdi.config = CSDI_CONFIG_INTER_DIR;
		cmd->csdi.config2 = CSDI_CONFIG2_DFLT;
		cmd->csdi.dcdi_config = CSDI_DCDI_CONFIG_DFLT;
	}

	/* Update hvsrc lut coef */
	scale_h = SCALE_FACTOR * dst_w / src_w;
	sti_hqvdp_update_hvsrc(HVSRC_HORI, scale_h, &cmd->hvsrc);

	scale_v = SCALE_FACTOR * dst_h / src_h;
	sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);

	writel(hqvdp->hqvdp_cmd_paddr + cmd_offset,
	       hqvdp->regs + HQVDP_MBX_NEXT_CMD);

	/* Interlaced : get ready to display the bottom field at next Vsync */
	if (fb->flags & DRM_MODE_FB_INTERLACED)
		hqvdp->btm_field_pending = true;

	dev_dbg(hqvdp->dev, "%s Posted command:0x%x\n",
		__func__, hqvdp->hqvdp_cmd_paddr + cmd_offset);

	sti_plane_update_fps(plane, true, true);

	plane->status = STI_PLANE_UPDATED;
}
Ejemplo n.º 10
0
static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
				  struct drm_plane_state *state)
{
	struct sti_plane *plane = to_sti_plane(drm_plane);
	struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
	struct drm_crtc *crtc = state->crtc;
	struct drm_framebuffer *fb = state->fb;
	bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
	struct drm_crtc_state *crtc_state;
	struct drm_display_mode *mode;
	int dst_x, dst_y, dst_w, dst_h;
	int src_x, src_y, src_w, src_h;

	/* no need for further checks if the plane is being disabled */
	if (!crtc || !fb)
		return 0;

	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
	mode = &crtc_state->mode;
	dst_x = state->crtc_x;
	dst_y = state->crtc_y;
	dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
	dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
	/* src_x are in 16.16 format */
	src_x = state->src_x >> 16;
	src_y = state->src_y >> 16;
	src_w = state->src_w >> 16;
	src_h = state->src_h >> 16;

	if (!sti_hqvdp_check_hw_scaling(hqvdp, mode,
					src_w, src_h,
					dst_w, dst_h)) {
		DRM_ERROR("Scaling beyond HW capabilities\n");
		return -EINVAL;
	}

	if (!drm_fb_cma_get_gem_obj(fb, 0)) {
		DRM_ERROR("Can't get CMA GEM object for fb\n");
		return -EINVAL;
	}

	/*
	 * Input / output size
	 * Align to upper even value
	 */
	dst_w = ALIGN(dst_w, 2);
	dst_h = ALIGN(dst_h, 2);

	if ((src_w > MAX_WIDTH) || (src_w < MIN_WIDTH) ||
	    (src_h > MAX_HEIGHT) || (src_h < MIN_HEIGHT) ||
	    (dst_w > MAX_WIDTH) || (dst_w < MIN_WIDTH) ||
	    (dst_h > MAX_HEIGHT) || (dst_h < MIN_HEIGHT)) {
		DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
			  src_w, src_h,
			  dst_w, dst_h);
		return -EINVAL;
	}

	if (first_prepare) {
		/* Start HQVDP XP70 coprocessor */
		sti_hqvdp_start_xp70(hqvdp);

		/* Prevent VTG shutdown */
		if (clk_prepare_enable(hqvdp->clk_pix_main)) {
			DRM_ERROR("Failed to prepare/enable pix main clk\n");
			return -EINVAL;
		}

		/* Register VTG Vsync callback to handle bottom fields */
		if (sti_vtg_register_client(hqvdp->vtg,
					    &hqvdp->vtg_nb,
					    crtc)) {
			DRM_ERROR("Cannot register VTG notifier\n");
			return -EINVAL;
		}
	}

	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
		      crtc->base.id, sti_mixer_to_str(to_sti_mixer(crtc)),
		      drm_plane->base.id, sti_plane_to_str(plane));
	DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n",
		      sti_plane_to_str(plane),
		      dst_w, dst_h, dst_x, dst_y,
		      src_w, src_h, src_x, src_y);

	return 0;
}
Ejemplo n.º 11
0
static int ipu_page_flip(struct drm_crtc *crtc,
		struct drm_framebuffer *fb,
		struct drm_pending_vblank_event *event,
		uint32_t page_flip_flags)
{
	struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
	struct ipu_flip_work *flip_work;
	int ret;

	if (ipu_crtc->flip_state != IPU_FLIP_NONE)
		return -EBUSY;

	ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc);
	if (ret) {
		dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n");
		list_del(&event->base.link);

		return ret;
	}

	flip_work = kzalloc(sizeof *flip_work, GFP_KERNEL);
	if (!flip_work) {
		ret = -ENOMEM;
		goto put_vblank;
	}
	INIT_WORK(&flip_work->unref_work, ipu_flip_unref_work_func);
	flip_work->page_flip_event = event;

	/* get BO backing the old framebuffer and take a reference */
	flip_work->bo = &drm_fb_cma_get_gem_obj(crtc->primary->fb, 0)->base;
	drm_gem_object_reference(flip_work->bo);

	ipu_crtc->flip_work = flip_work;
	/*
	 * If the object has a DMABUF attached, we need to wait on its fences
	 * if there are any.
	 */
	if (cma_obj->base.dma_buf) {
		INIT_WORK(&flip_work->fence_work, ipu_flip_fence_work_func);
		flip_work->crtc = ipu_crtc;

		ret = reservation_object_get_fences_rcu(
				cma_obj->base.dma_buf->resv, &flip_work->excl,
				&flip_work->shared_count, &flip_work->shared);

		if (unlikely(ret)) {
			DRM_ERROR("failed to get fences for buffer\n");
			goto free_flip_work;
		}

		/* No need to queue the worker if the are no fences */
		if (!flip_work->excl && !flip_work->shared_count) {
			ipu_crtc->flip_state = IPU_FLIP_SUBMITTED;
		} else {
			ipu_crtc->flip_state = IPU_FLIP_PENDING;
			queue_work(ipu_crtc->flip_queue,
				   &flip_work->fence_work);
		}
	} else {
		ipu_crtc->flip_state = IPU_FLIP_SUBMITTED;
	}

	return 0;

free_flip_work:
	drm_gem_object_unreference_unlocked(flip_work->bo);
	kfree(flip_work);
	ipu_crtc->flip_work = NULL;
put_vblank:
	imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc);

	return ret;
}
Ejemplo n.º 12
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;
}