From 247fa56c8dbc421ef2a1d0d241cfa420cac7b733 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 13 Sep 2022 11:00:10 +0800 Subject: [PATCH] drm/rockchip: vop2: Fix the pixel/yrgb_mst/uv_mst alignments of NV15/NV12 at splice mode The mst of yrgb/uv must start at a byte aligned address with a full group of pixel. For a pixel with NV15 format, the y channel has 10 bits and uv channel has 5 bits. So limit the alignment to 8 pixel(10 bytes for Y, and 5 bytes for UV) to meet this requirement. For a pixel with NV12 format, we should limit the alignment to 2 pixel. Change-Id: I23eccca6d706d3da25d2deac29e5a862e4bf355d Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index b02b2cce89e9..6fdd71acfdfe 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -4344,6 +4344,8 @@ static void vop2_calc_drm_rect_for_splice(struct vop2_plane_state *vpstate, int dst_w = drm_rect_width(dst); int src_w = drm_rect_width(src) >> 16; int left_src_w, left_dst_w, right_dst_w; + struct drm_plane_state *pstate = &vpstate->base; + struct drm_framebuffer *fb = pstate->fb; left_dst_w = min_t(u16, half_hdisplay, dst->x2) - dst->x1; if (left_dst_w < 0) @@ -4354,6 +4356,17 @@ static void vop2_calc_drm_rect_for_splice(struct vop2_plane_state *vpstate, left_src_w = src_w; else left_src_w = (left_dst_w * hscale) >> 16; + + /* + * Make sure the yrgb/uv mst of right win are byte aligned + * with full pixel. + */ + if (right_dst_w) { + if (fb->format->format == DRM_FORMAT_NV15) + left_src_w &= ~0x7; + else if (fb->format->format == DRM_FORMAT_NV12) + left_src_w &= ~0x1; + } left_src->x1 = src->x1; left_src->x2 = src->x1 + (left_src_w << 16); left_dst->x1 = dst->x1; @@ -4361,6 +4374,9 @@ static void vop2_calc_drm_rect_for_splice(struct vop2_plane_state *vpstate, right_src->x1 = left_src->x2; right_src->x2 = src->x2; right_dst->x1 = dst->x1 + left_dst_w - half_hdisplay; + if (right_dst->x1 < 0) + right_dst->x1 = 0; + right_dst->x2 = right_dst->x1 + right_dst_w; left_src->y1 = src->y1;