Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1480476 > unrolled thread

[PATCH 1/3] drm/rockchip: vop: move dma_addr to plane atomic check

Started byMark Yao <mark.yao@rock-chips.com>
First post2016-09-10 04:30 +0200
Last post2016-09-10 05:20 +0200
Articles 5 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 1/3] drm/rockchip: vop: move dma_addr to plane atomic check Mark Yao <mark.yao@rock-chips.com> - 2016-09-10 04:30 +0200
    [PATCH 3/3] drm/rockchip: vop: support afdc for rk3399 vop Mark Yao <mark.yao@rock-chips.com> - 2016-09-10 04:30 +0200
      [PATCH] drm/rockchip: vop: support afbc format for rk3399 vop Mark Yao <mark.yao@rock-chips.com> - 2016-09-10 05:10 +0200
        Re: [PATCH] drm/rockchip: vop: support afbc format for rk3399 vop Mark yao <mark.yao@rock-chips.com> - 2016-09-10 05:20 +0200
      [PATCH 3/3 v1.1] drm/rockchip: vop: support afbc format for rk3399 vop Mark Yao <mark.yao@rock-chips.com> - 2016-09-10 05:20 +0200

#1480476 — [PATCH 1/3] drm/rockchip: vop: move dma_addr to plane atomic check

FromMark Yao <mark.yao@rock-chips.com>
Date2016-09-10 04:30 +0200
Subject[PATCH 1/3] drm/rockchip: vop: move dma_addr to plane atomic check
Message-ID<sfGdj-2HO-7@gated-at.bofh.it>
Calc dma_addr earlier, then the dma_addr can be used on
crtc atomic check.

Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 52 ++++++++++++++++-------------
 1 file changed, 29 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3321115..834456f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -91,6 +91,7 @@ struct vop_plane_state {
 	struct drm_plane_state base;
 	int format;
 	dma_addr_t yrgb_mst;
+	dma_addr_t uv_mst;
 	bool enable;
 };
 
@@ -589,12 +590,16 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 	struct vop_win *vop_win = to_vop_win(plane);
 	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
 	const struct vop_win_data *win = vop_win->data;
+	struct drm_gem_object *obj, *uv_obj;
+	struct rockchip_gem_object *rk_obj, *rk_uv_obj;
 	int ret;
+	struct drm_rect *src = &state->src;
 	struct drm_rect clip;
 	int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
 					DRM_PLANE_HELPER_NO_SCALING;
 	int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
 					DRM_PLANE_HELPER_NO_SCALING;
+	unsigned long offset;
 
 	if (!crtc || !fb)
 		goto out_disable;
@@ -628,6 +633,29 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 	if (is_yuv_support(fb->pixel_format) && ((state->src.x1 >> 16) % 2))
 		return -EINVAL;
 
+	obj = rockchip_fb_get_gem_obj(fb, 0);
+	rk_obj = to_rockchip_obj(obj);
+
+	offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
+	offset += (src->y1 >> 16) * fb->pitches[0];
+	offset += fb->offsets[0];
+	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset;
+
+	if (is_yuv_support(fb->pixel_format)) {
+		int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
+		int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
+		int bpp = drm_format_plane_cpp(fb->pixel_format, 1);
+
+		uv_obj = rockchip_fb_get_gem_obj(fb, 1);
+		rk_uv_obj = to_rockchip_obj(uv_obj);
+
+		offset = (src->x1 >> 16) * bpp / hsub;
+		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
+		offset += fb->offsets[1];
+
+		vop_plane_state->uv_mst = rk_uv_obj->dma_addr + offset;
+	}
+
 	vop_plane_state->enable = true;
 
 	return 0;
@@ -677,10 +705,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	uint32_t act_info, dsp_info, dsp_st;
 	struct drm_rect *src = &state->src;
 	struct drm_rect *dest = &state->dst;
-	struct drm_gem_object *obj, *uv_obj;
-	struct rockchip_gem_object *rk_obj, *rk_uv_obj;
-	unsigned long offset;
-	dma_addr_t dma_addr;
 	uint32_t val;
 	bool rb_swap;
 
@@ -698,9 +722,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 		return;
 	}
 
-	obj = rockchip_fb_get_gem_obj(fb, 0);
-	rk_obj = to_rockchip_obj(obj);
-
 	actual_w = drm_rect_width(src) >> 16;
 	actual_h = drm_rect_height(src) >> 16;
 	act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
@@ -712,10 +733,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	dsp_sty = dest->y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
 	dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff);
 
-	offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
-	offset += (src->y1 >> 16) * fb->pitches[0];
-	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
-
 	spin_lock_irq(&plane->dev->event_lock);
 	vop_win->enable = true;
 	vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
@@ -727,19 +744,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
 	VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst);
 	if (is_yuv_support(fb->pixel_format)) {
-		int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
-		int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
-		int bpp = drm_format_plane_cpp(fb->pixel_format, 1);
-
-		uv_obj = rockchip_fb_get_gem_obj(fb, 1);
-		rk_uv_obj = to_rockchip_obj(uv_obj);
-
-		offset = (src->x1 >> 16) * bpp / hsub;
-		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
-
-		dma_addr = rk_uv_obj->dma_addr + offset + fb->offsets[1];
 		VOP_WIN_SET(vop, win, uv_vir, fb->pitches[1] >> 2);
-		VOP_WIN_SET(vop, win, uv_mst, dma_addr);
+		VOP_WIN_SET(vop, win, uv_mst, vop_plane_state->uv_mst);
 	}
 
 	if (win->phy->scl)
-- 
1.9.1

[toc] | [next] | [standalone]


#1480478 — [PATCH 3/3] drm/rockchip: vop: support afdc for rk3399 vop

FromMark Yao <mark.yao@rock-chips.com>
Date2016-09-10 04:30 +0200
Subject[PATCH 3/3] drm/rockchip: vop: support afdc for rk3399 vop
Message-ID<sfGdk-2HO-21@gated-at.bofh.it>
In reply to#1480476
Rk3399 vop big can support one afbc decoder, the afbdc decoder
can select which overlay window use it.

afbdc window has some limit:
  1, not support offset on source buffer.
  2, if feed non-afbc buffer to afbc decoder, afbc decoder hardware
     would die, we need take care of using it.

AFBC is a compressed format, means lower bandwidth consume,
it's useful to improve performance.

Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  6 ++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 89 +++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 13 +++++
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |  7 +++
 4 files changed, 115 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..1e07fd6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -44,6 +44,12 @@ struct rockchip_crtc_funcs {
 
 struct rockchip_crtc_state {
 	struct drm_crtc_state base;
+	int afbdc_win_format;
+	int afbdc_win_width;
+	int afbdc_win_height;
+	int afbdc_win_ptr;
+	int afbdc_win_id;
+	int afbdc_en;
 	int output_type;
 	int output_mode;
 };
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 834456f..6918223 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -99,6 +99,7 @@ struct vop_win {
 	struct drm_plane base;
 	const struct vop_win_data *data;
 	struct vop *vop;
+	int id;
 
 	/* protected by dev->event_lock */
 	bool enable;
@@ -514,6 +515,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
 		VOP_WIN_SET(vop, win, enable, 0);
 		spin_unlock(&vop->reg_lock);
 	}
+	VOP_CTRL_SET(vop, afbdc_en, 0);
 
 	drm_crtc_vblank_off(crtc);
 
@@ -1007,9 +1009,81 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 	VOP_CTRL_SET(vop, standby, 0);
 }
 
+static int vop_afbdc_atomic_check(struct drm_crtc *crtc,
+				  struct drm_crtc_state *crtc_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+	struct drm_atomic_state *state = crtc_state->state;
+	struct drm_plane *plane;
+	struct drm_plane_state *pstate;
+	struct vop_plane_state *plane_state;
+	struct vop_win *win;
+	int afbdc_format;
+	int i;
+
+	s->afbdc_en = 0;
+
+	for_each_plane_in_state(state, plane, pstate, i) {
+		struct drm_framebuffer *fb = pstate->fb;
+		struct drm_rect *src;
+
+		win = to_vop_win(plane);
+		plane_state = to_vop_plane_state(pstate);
+
+		if (pstate->crtc != crtc || !fb)
+			continue;
+
+		if (fb->modifier[0] != DRM_FORMAT_MOD_ARM_AFBC)
+			continue;
+
+		switch (plane_state->format) {
+		case VOP_FMT_ARGB8888:
+			afbdc_format = AFBDC_FMT_U8U8U8U8;
+			break;
+		case VOP_FMT_RGB888:
+			afbdc_format = AFBDC_FMT_U8U8U8;
+			break;
+		case VOP_FMT_RGB565:
+			afbdc_format = AFBDC_FMT_RGB565;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (s->afbdc_en) {
+			DRM_ERROR("vop only support one afbc layer\n");
+			return -EINVAL;
+		}
+
+		src = &pstate->src;
+		if (src->x1 || src->y1 || fb->offsets[0]) {
+			DRM_ERROR("win[%d] afbdc not support offset display\n",
+				  win->id);
+			DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n",
+				  src->x1, src->y1, fb->offsets[0]);
+			return -EINVAL;
+		}
+		s->afbdc_win_format = afbdc_format;
+		s->afbdc_win_width = pstate->fb->width - 1;
+		s->afbdc_win_height = (drm_rect_height(src) >> 16) - 1;
+		s->afbdc_win_id = win->id;
+		s->afbdc_win_ptr = plane_state->yrgb_mst;
+		s->afbdc_en = 1;
+	}
+
+	return 0;
+}
+
+static int vop_crtc_atomic_check(struct drm_crtc *crtc,
+				 struct drm_crtc_state *crtc_state)
+{
+	return vop_afbdc_atomic_check(crtc, crtc_state);
+}
+
 static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 				  struct drm_crtc_state *old_crtc_state)
 {
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
 	struct vop *vop = to_vop(crtc);
 
 	if (WARN_ON(!vop->is_enabled))
@@ -1017,6 +1091,19 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	spin_lock(&vop->reg_lock);
 
+	if (s->afbdc_en) {
+		uint32_t pic_size;
+
+		VOP_CTRL_SET(vop, afbdc_format, s->afbdc_win_format | 1 << 4);
+		VOP_CTRL_SET(vop, afbdc_hreg_block_split, 0);
+		VOP_CTRL_SET(vop, afbdc_sel, s->afbdc_win_id);
+		VOP_CTRL_SET(vop, afbdc_hdr_ptr, s->afbdc_win_ptr);
+		pic_size = (s->afbdc_win_width & 0xffff);
+		pic_size |= s->afbdc_win_height << 16;
+		VOP_CTRL_SET(vop, afbdc_pic_size, pic_size);
+	}
+
+	VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
 	vop_cfg_done(vop);
 
 	spin_unlock(&vop->reg_lock);
@@ -1042,6 +1129,7 @@ static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
 	.enable = vop_crtc_enable,
 	.disable = vop_crtc_disable,
 	.mode_fixup = vop_crtc_mode_fixup,
+	.atomic_check = vop_crtc_atomic_check,
 	.atomic_flush = vop_crtc_atomic_flush,
 	.atomic_begin = vop_crtc_atomic_begin,
 };
@@ -1413,6 +1501,7 @@ static void vop_win_init(struct vop *vop)
 		struct vop_win *vop_win = &vop->win[i];
 		const struct vop_win_data *win_data = &vop_data->win[i];
 
+		vop_win->id = i;
 		vop_win->data = win_data;
 		vop_win->vop = vop;
 	}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index ff4f52e..b9b120e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -15,6 +15,10 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
+#define AFBDC_FMT_RGB565	0x0
+#define AFBDC_FMT_U8U8U8U8	0x5
+#define AFBDC_FMT_U8U8U8	0x4
+
 enum vop_data_format {
 	VOP_FMT_ARGB8888 = 0,
 	VOP_FMT_RGB888,
@@ -61,6 +65,15 @@ struct vop_ctrl {
 	struct vop_reg hpost_st_end;
 	struct vop_reg vpost_st_end;
 
+	/* AFBDC */
+	struct vop_reg afbdc_en;
+	struct vop_reg afbdc_sel;
+	struct vop_reg afbdc_format;
+	struct vop_reg afbdc_hreg_block_split;
+	struct vop_reg afbdc_pic_size;
+	struct vop_reg afbdc_hdr_ptr;
+	struct vop_reg afbdc_rstn;
+
 	struct vop_reg cfg_done;
 };
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index f1a1688..a09437c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -300,6 +300,13 @@ static const struct vop_ctrl rk3399_ctrl_data = {
 	.vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0),
 	.hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
 	.vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.afbdc_rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
+	.afbdc_en = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
+	.afbdc_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
+	.afbdc_format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
+	.afbdc_hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
+	.afbdc_hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
+	.afbdc_pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
 	.cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0),
 };
 
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1480483 — [PATCH] drm/rockchip: vop: support afbc format for rk3399 vop

FromMark Yao <mark.yao@rock-chips.com>
Date2016-09-10 05:10 +0200
Subject[PATCH] drm/rockchip: vop: support afbc format for rk3399 vop
Message-ID<sfGQ1-38Y-7@gated-at.bofh.it>
In reply to#1480478
Rk3399 vop big can support one afbc decoder, the afbc decoder
can select which overlay window use it.

on vop hardware, we call afbc decoder as afbdc.

afbdc window has some limit:
  1, not support offset on source buffer.
  2, if feed non-afbc buffer to afbc decoder, afbc decoder hardware
     would die, we need take care of using it.

AFBC is a compressed format, means lower bandwidth consume,
it's useful to improve performance.

Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  6 ++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 89 +++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 13 +++++
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |  7 +++
 4 files changed, 115 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..1e07fd6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -44,6 +44,12 @@ struct rockchip_crtc_funcs {
 
 struct rockchip_crtc_state {
 	struct drm_crtc_state base;
+	int afbdc_win_format;
+	int afbdc_win_width;
+	int afbdc_win_height;
+	int afbdc_win_ptr;
+	int afbdc_win_id;
+	int afbdc_en;
 	int output_type;
 	int output_mode;
 };
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 834456f..6918223 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -99,6 +99,7 @@ struct vop_win {
 	struct drm_plane base;
 	const struct vop_win_data *data;
 	struct vop *vop;
+	int id;
 
 	/* protected by dev->event_lock */
 	bool enable;
@@ -514,6 +515,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
 		VOP_WIN_SET(vop, win, enable, 0);
 		spin_unlock(&vop->reg_lock);
 	}
+	VOP_CTRL_SET(vop, afbdc_en, 0);
 
 	drm_crtc_vblank_off(crtc);
 
@@ -1007,9 +1009,81 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 	VOP_CTRL_SET(vop, standby, 0);
 }
 
+static int vop_afbdc_atomic_check(struct drm_crtc *crtc,
+				  struct drm_crtc_state *crtc_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+	struct drm_atomic_state *state = crtc_state->state;
+	struct drm_plane *plane;
+	struct drm_plane_state *pstate;
+	struct vop_plane_state *plane_state;
+	struct vop_win *win;
+	int afbdc_format;
+	int i;
+
+	s->afbdc_en = 0;
+
+	for_each_plane_in_state(state, plane, pstate, i) {
+		struct drm_framebuffer *fb = pstate->fb;
+		struct drm_rect *src;
+
+		win = to_vop_win(plane);
+		plane_state = to_vop_plane_state(pstate);
+
+		if (pstate->crtc != crtc || !fb)
+			continue;
+
+		if (fb->modifier[0] != DRM_FORMAT_MOD_ARM_AFBC)
+			continue;
+
+		switch (plane_state->format) {
+		case VOP_FMT_ARGB8888:
+			afbdc_format = AFBDC_FMT_U8U8U8U8;
+			break;
+		case VOP_FMT_RGB888:
+			afbdc_format = AFBDC_FMT_U8U8U8;
+			break;
+		case VOP_FMT_RGB565:
+			afbdc_format = AFBDC_FMT_RGB565;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (s->afbdc_en) {
+			DRM_ERROR("vop only support one afbc layer\n");
+			return -EINVAL;
+		}
+
+		src = &pstate->src;
+		if (src->x1 || src->y1 || fb->offsets[0]) {
+			DRM_ERROR("win[%d] afbdc not support offset display\n",
+				  win->id);
+			DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n",
+				  src->x1, src->y1, fb->offsets[0]);
+			return -EINVAL;
+		}
+		s->afbdc_win_format = afbdc_format;
+		s->afbdc_win_width = pstate->fb->width - 1;
+		s->afbdc_win_height = (drm_rect_height(src) >> 16) - 1;
+		s->afbdc_win_id = win->id;
+		s->afbdc_win_ptr = plane_state->yrgb_mst;
+		s->afbdc_en = 1;
+	}
+
+	return 0;
+}
+
+static int vop_crtc_atomic_check(struct drm_crtc *crtc,
+				 struct drm_crtc_state *crtc_state)
+{
+	return vop_afbdc_atomic_check(crtc, crtc_state);
+}
+
 static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 				  struct drm_crtc_state *old_crtc_state)
 {
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
 	struct vop *vop = to_vop(crtc);
 
 	if (WARN_ON(!vop->is_enabled))
@@ -1017,6 +1091,19 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	spin_lock(&vop->reg_lock);
 
+	if (s->afbdc_en) {
+		uint32_t pic_size;
+
+		VOP_CTRL_SET(vop, afbdc_format, s->afbdc_win_format | 1 << 4);
+		VOP_CTRL_SET(vop, afbdc_hreg_block_split, 0);
+		VOP_CTRL_SET(vop, afbdc_sel, s->afbdc_win_id);
+		VOP_CTRL_SET(vop, afbdc_hdr_ptr, s->afbdc_win_ptr);
+		pic_size = (s->afbdc_win_width & 0xffff);
+		pic_size |= s->afbdc_win_height << 16;
+		VOP_CTRL_SET(vop, afbdc_pic_size, pic_size);
+	}
+
+	VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
 	vop_cfg_done(vop);
 
 	spin_unlock(&vop->reg_lock);
@@ -1042,6 +1129,7 @@ static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
 	.enable = vop_crtc_enable,
 	.disable = vop_crtc_disable,
 	.mode_fixup = vop_crtc_mode_fixup,
+	.atomic_check = vop_crtc_atomic_check,
 	.atomic_flush = vop_crtc_atomic_flush,
 	.atomic_begin = vop_crtc_atomic_begin,
 };
@@ -1413,6 +1501,7 @@ static void vop_win_init(struct vop *vop)
 		struct vop_win *vop_win = &vop->win[i];
 		const struct vop_win_data *win_data = &vop_data->win[i];
 
+		vop_win->id = i;
 		vop_win->data = win_data;
 		vop_win->vop = vop;
 	}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index ff4f52e..b9b120e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -15,6 +15,10 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
+#define AFBDC_FMT_RGB565	0x0
+#define AFBDC_FMT_U8U8U8U8	0x5
+#define AFBDC_FMT_U8U8U8	0x4
+
 enum vop_data_format {
 	VOP_FMT_ARGB8888 = 0,
 	VOP_FMT_RGB888,
@@ -61,6 +65,15 @@ struct vop_ctrl {
 	struct vop_reg hpost_st_end;
 	struct vop_reg vpost_st_end;
 
+	/* AFBDC */
+	struct vop_reg afbdc_en;
+	struct vop_reg afbdc_sel;
+	struct vop_reg afbdc_format;
+	struct vop_reg afbdc_hreg_block_split;
+	struct vop_reg afbdc_pic_size;
+	struct vop_reg afbdc_hdr_ptr;
+	struct vop_reg afbdc_rstn;
+
 	struct vop_reg cfg_done;
 };
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index f1a1688..a09437c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -300,6 +300,13 @@ static const struct vop_ctrl rk3399_ctrl_data = {
 	.vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0),
 	.hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
 	.vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.afbdc_rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
+	.afbdc_en = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
+	.afbdc_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
+	.afbdc_format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
+	.afbdc_hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
+	.afbdc_hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
+	.afbdc_pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
 	.cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0),
 };
 
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1480487 — Re: [PATCH] drm/rockchip: vop: support afbc format for rk3399 vop

FromMark yao <mark.yao@rock-chips.com>
Date2016-09-10 05:20 +0200
SubjectRe: [PATCH] drm/rockchip: vop: support afbc format for rk3399 vop
Message-ID<sfGZH-3c2-7@gated-at.bofh.it>
In reply to#1480483
Sorry, wrong title on this mail, ignore this mail. I had resent it.
On 2016年09月10日 11:07, Mark Yao wrote:
> Rk3399 vop big can support one afbc decoder, the afbc decoder
> can select which overlay window use it.
>
> on vop hardware, we call afbc decoder as afbdc.
>
> afbdc window has some limit:
>    1, not support offset on source buffer.
>    2, if feed non-afbc buffer to afbc decoder, afbc decoder hardware
>       would die, we need take care of using it.
>
> AFBC is a compressed format, means lower bandwidth consume,
> it's useful to improve performance.
>
> Signed-off-by: Mark Yao<mark.yao@rock-chips.com>
> ---


-- 
Mark Yao

[toc] | [prev] | [next] | [standalone]


#1480484 — [PATCH 3/3 v1.1] drm/rockchip: vop: support afbc format for rk3399 vop

FromMark Yao <mark.yao@rock-chips.com>
Date2016-09-10 05:20 +0200
Subject[PATCH 3/3 v1.1] drm/rockchip: vop: support afbc format for rk3399 vop
Message-ID<sfGZH-3c2-1@gated-at.bofh.it>
In reply to#1480478
Rk3399 vop big can support one afbc decoder, the afbc decoder
can select which overlay window use it.

on vop hardware, we call afbc decoder as afbdc.

afbdc window has some limit:
  1, not support offset on source buffer.
  2, if feed non-afbc buffer to afbc decoder, afbc decoder hardware
     would die, we need take care of using it.

AFBC is a compressed format, means lower bandwidth consume,
it's useful to improve performance.

Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
changes in v1.1
  correct some comment.

 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  6 ++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 89 +++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 13 +++++
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |  7 +++
 4 files changed, 115 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index ea39329..1e07fd6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -44,6 +44,12 @@ struct rockchip_crtc_funcs {
 
 struct rockchip_crtc_state {
 	struct drm_crtc_state base;
+	int afbdc_win_format;
+	int afbdc_win_width;
+	int afbdc_win_height;
+	int afbdc_win_ptr;
+	int afbdc_win_id;
+	int afbdc_en;
 	int output_type;
 	int output_mode;
 };
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 834456f..6918223 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -99,6 +99,7 @@ struct vop_win {
 	struct drm_plane base;
 	const struct vop_win_data *data;
 	struct vop *vop;
+	int id;
 
 	/* protected by dev->event_lock */
 	bool enable;
@@ -514,6 +515,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
 		VOP_WIN_SET(vop, win, enable, 0);
 		spin_unlock(&vop->reg_lock);
 	}
+	VOP_CTRL_SET(vop, afbdc_en, 0);
 
 	drm_crtc_vblank_off(crtc);
 
@@ -1007,9 +1009,81 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 	VOP_CTRL_SET(vop, standby, 0);
 }
 
+static int vop_afbdc_atomic_check(struct drm_crtc *crtc,
+				  struct drm_crtc_state *crtc_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+	struct drm_atomic_state *state = crtc_state->state;
+	struct drm_plane *plane;
+	struct drm_plane_state *pstate;
+	struct vop_plane_state *plane_state;
+	struct vop_win *win;
+	int afbdc_format;
+	int i;
+
+	s->afbdc_en = 0;
+
+	for_each_plane_in_state(state, plane, pstate, i) {
+		struct drm_framebuffer *fb = pstate->fb;
+		struct drm_rect *src;
+
+		win = to_vop_win(plane);
+		plane_state = to_vop_plane_state(pstate);
+
+		if (pstate->crtc != crtc || !fb)
+			continue;
+
+		if (fb->modifier[0] != DRM_FORMAT_MOD_ARM_AFBC)
+			continue;
+
+		switch (plane_state->format) {
+		case VOP_FMT_ARGB8888:
+			afbdc_format = AFBDC_FMT_U8U8U8U8;
+			break;
+		case VOP_FMT_RGB888:
+			afbdc_format = AFBDC_FMT_U8U8U8;
+			break;
+		case VOP_FMT_RGB565:
+			afbdc_format = AFBDC_FMT_RGB565;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (s->afbdc_en) {
+			DRM_ERROR("vop only support one afbc layer\n");
+			return -EINVAL;
+		}
+
+		src = &pstate->src;
+		if (src->x1 || src->y1 || fb->offsets[0]) {
+			DRM_ERROR("win[%d] afbdc not support offset display\n",
+				  win->id);
+			DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n",
+				  src->x1, src->y1, fb->offsets[0]);
+			return -EINVAL;
+		}
+		s->afbdc_win_format = afbdc_format;
+		s->afbdc_win_width = pstate->fb->width - 1;
+		s->afbdc_win_height = (drm_rect_height(src) >> 16) - 1;
+		s->afbdc_win_id = win->id;
+		s->afbdc_win_ptr = plane_state->yrgb_mst;
+		s->afbdc_en = 1;
+	}
+
+	return 0;
+}
+
+static int vop_crtc_atomic_check(struct drm_crtc *crtc,
+				 struct drm_crtc_state *crtc_state)
+{
+	return vop_afbdc_atomic_check(crtc, crtc_state);
+}
+
 static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 				  struct drm_crtc_state *old_crtc_state)
 {
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
 	struct vop *vop = to_vop(crtc);
 
 	if (WARN_ON(!vop->is_enabled))
@@ -1017,6 +1091,19 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	spin_lock(&vop->reg_lock);
 
+	if (s->afbdc_en) {
+		uint32_t pic_size;
+
+		VOP_CTRL_SET(vop, afbdc_format, s->afbdc_win_format | 1 << 4);
+		VOP_CTRL_SET(vop, afbdc_hreg_block_split, 0);
+		VOP_CTRL_SET(vop, afbdc_sel, s->afbdc_win_id);
+		VOP_CTRL_SET(vop, afbdc_hdr_ptr, s->afbdc_win_ptr);
+		pic_size = (s->afbdc_win_width & 0xffff);
+		pic_size |= s->afbdc_win_height << 16;
+		VOP_CTRL_SET(vop, afbdc_pic_size, pic_size);
+	}
+
+	VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
 	vop_cfg_done(vop);
 
 	spin_unlock(&vop->reg_lock);
@@ -1042,6 +1129,7 @@ static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
 	.enable = vop_crtc_enable,
 	.disable = vop_crtc_disable,
 	.mode_fixup = vop_crtc_mode_fixup,
+	.atomic_check = vop_crtc_atomic_check,
 	.atomic_flush = vop_crtc_atomic_flush,
 	.atomic_begin = vop_crtc_atomic_begin,
 };
@@ -1413,6 +1501,7 @@ static void vop_win_init(struct vop *vop)
 		struct vop_win *vop_win = &vop->win[i];
 		const struct vop_win_data *win_data = &vop_data->win[i];
 
+		vop_win->id = i;
 		vop_win->data = win_data;
 		vop_win->vop = vop;
 	}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index ff4f52e..b9b120e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -15,6 +15,10 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
+#define AFBDC_FMT_RGB565	0x0
+#define AFBDC_FMT_U8U8U8U8	0x5
+#define AFBDC_FMT_U8U8U8	0x4
+
 enum vop_data_format {
 	VOP_FMT_ARGB8888 = 0,
 	VOP_FMT_RGB888,
@@ -61,6 +65,15 @@ struct vop_ctrl {
 	struct vop_reg hpost_st_end;
 	struct vop_reg vpost_st_end;
 
+	/* AFBDC */
+	struct vop_reg afbdc_en;
+	struct vop_reg afbdc_sel;
+	struct vop_reg afbdc_format;
+	struct vop_reg afbdc_hreg_block_split;
+	struct vop_reg afbdc_pic_size;
+	struct vop_reg afbdc_hdr_ptr;
+	struct vop_reg afbdc_rstn;
+
 	struct vop_reg cfg_done;
 };
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index f1a1688..a09437c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -300,6 +300,13 @@ static const struct vop_ctrl rk3399_ctrl_data = {
 	.vact_st_end = VOP_REG(RK3399_DSP_VACT_ST_END, 0x1fff1fff, 0),
 	.hpost_st_end = VOP_REG(RK3399_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
 	.vpost_st_end = VOP_REG(RK3399_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.afbdc_rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
+	.afbdc_en = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
+	.afbdc_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
+	.afbdc_format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
+	.afbdc_hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
+	.afbdc_hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
+	.afbdc_pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
 	.cfg_done = VOP_REG_MASK(RK3399_REG_CFG_DONE, 0x1, 0),
 };
 
-- 
1.9.1

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web