From 18b66b881f3a22c396fe987ddc8563e849c9f6fa Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Wed, 18 Nov 2020 15:59:23 +0800 Subject: [PATCH] drm/rockchip: vop2: Add color components swap Change-Id: I124f92fadc2494311b950657bbb0176d65aff08b Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 3 ++ drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 55 ++++++++++++++++++-- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 6 +++ 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index ea7a178276f0..cd941b6aa404 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -311,6 +311,8 @@ struct vop_afbc { struct vop_reg enable; struct vop_reg win_sel; struct vop_reg format; + struct vop_reg rb_swap; + struct vop_reg uv_swap; struct vop_reg auto_gating_en; struct vop_reg rotate; struct vop_reg block_split_en; @@ -478,6 +480,7 @@ struct vop2_win_regs { struct vop_reg xmirror; struct vop_reg ymirror; struct vop_reg rb_swap; + struct vop_reg uv_swap; struct vop_reg act_info; struct vop_reg dsp_info; struct vop_reg dsp_st; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index b5eb1ab7f286..40b6a18db696 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -727,7 +727,7 @@ static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format) return -EINVAL; } -static bool has_rb_swapped(uint32_t format) +static bool vop2_win_rb_swap(uint32_t format) { switch (format) { case DRM_FORMAT_XBGR8888: @@ -740,7 +740,46 @@ static bool has_rb_swapped(uint32_t format) } } -static bool is_uv_swap(uint32_t bus_format, uint32_t output_mode) +static bool vop2_afbc_rb_swap(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_NV24: + case DRM_FORMAT_NV24_10: + return true; + default: + return false; + } +} + +static bool vop2_afbc_uv_swap(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV12_10: + case DRM_FORMAT_NV16_10: + return true; + default: + return false; + } +} + +static bool vop2_win_uv_swap(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV24: + case DRM_FORMAT_NV12_10: + case DRM_FORMAT_NV16_10: + case DRM_FORMAT_NV24_10: + return true; + default: + return false; + } +} + +static bool vop2_output_uv_swap(uint32_t bus_format, uint32_t output_mode) { /* * FIXME: @@ -759,6 +798,7 @@ static bool is_uv_swap(uint32_t bus_format, uint32_t output_mode) else return false; } + static bool is_yuv_support(uint32_t format) { switch (format) { @@ -1560,6 +1600,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s uint32_t format; uint32_t afbc_format; uint32_t rb_swap; + uint32_t uv_swap; struct drm_rect *src = &vpstate->src; struct drm_rect *dest = &vpstate->dest; uint32_t afbc_tile_num; @@ -1630,9 +1671,13 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s * with WIN_VIR_STRIDE. */ stride = (fb->pitches[0] << 3) / bpp; + rb_swap = vop2_afbc_rb_swap(fb->format->format); + uv_swap = vop2_afbc_uv_swap(fb->format->format); afbc_half_block_en = vop2_afbc_half_block_enable(vpstate); VOP_AFBC_SET(vop2, win, enable, 1); VOP_AFBC_SET(vop2, win, format, afbc_format); + VOP_AFBC_SET(vop2, win, rb_swap, rb_swap); + VOP_AFBC_SET(vop2, win, uv_swap, uv_swap); VOP_AFBC_SET(vop2, win, auto_gating_en, 0); VOP_AFBC_SET(vop2, win, block_split_en, 0); VOP_AFBC_SET(vop2, win, half_block_en, afbc_half_block_en); @@ -1663,8 +1708,10 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s VOP_WIN_SET(vop2, win, yrgb_vir, stride); VOP_WIN_SET(vop2, win, yrgb_mst, vpstate->yrgb_mst); - rb_swap = has_rb_swapped(fb->format->format); + rb_swap = vop2_win_rb_swap(fb->format->format); + uv_swap = vop2_win_uv_swap(fb->format->format); VOP_WIN_SET(vop2, win, rb_swap, rb_swap); + VOP_WIN_SET(vop2, win, uv_swap, uv_swap); if (fb->format->is_yuv) { VOP_WIN_SET(vop2, win, uv_vir, DIV_ROUND_UP(fb->pitches[1], 4)); @@ -2711,7 +2758,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state VOP_MODULE_SET(vop2, vp, out_mode, out_mode); VOP_MODULE_SET(vop2, vp, overlay_mode, is_yuv_output(vcstate->bus_format)); - if (is_uv_swap(vcstate->bus_format, vcstate->output_mode)) + if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode)) VOP_MODULE_SET(vop2, vp, dsp_data_swap, DSP_RB_SWAP); else VOP_MODULE_SET(vop2, vp, dsp_data_swap, 0); diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index fb3249c062cf..2fd658ef6911 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -553,6 +553,8 @@ static const struct vop2_layer_data rk3568_vop_layers[] = { static const struct vop_afbc rk3568_vop_afbc = { .enable = VOP_REG(RK3568_CLUSTER0_CTRL, 0x1, 1), .format = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1f, 2), + .rb_swap = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 9), + .uv_swap = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 10), .auto_gating_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_OUTPUT_CTRL, 0x1, 4), .half_block_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 7), .block_split_en = VOP_REG(RK3568_CLUSTER0_WIN0_AFBCD_CTRL, 0x1, 8), @@ -661,6 +663,7 @@ static const struct vop2_win_regs rk3568_area1_data = { .enable = VOP_REG(RK3568_ESMART0_REGION1_CTRL, 0x1, 0), .format = VOP_REG(RK3568_ESMART0_REGION1_CTRL, 0x1f, 1), .rb_swap = VOP_REG(RK3568_ESMART0_REGION1_CTRL, 0x1, 14), + .uv_swap = VOP_REG(RK3568_ESMART0_REGION1_CTRL, 0x1, 16), .act_info = VOP_REG(RK3568_ESMART0_REGION1_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3568_ESMART0_REGION1_DSP_INFO, 0x1fff1fff, 0), .dsp_st = VOP_REG(RK3568_ESMART0_REGION1_DSP_ST, 0x1fff1fff, 0), @@ -675,6 +678,7 @@ static const struct vop2_win_regs rk3568_area2_data = { .enable = VOP_REG(RK3568_ESMART0_REGION2_CTRL, 0x1, 0), .format = VOP_REG(RK3568_ESMART0_REGION2_CTRL, 0x1f, 1), .rb_swap = VOP_REG(RK3568_ESMART0_REGION2_CTRL, 0x1, 14), + .uv_swap = VOP_REG(RK3568_ESMART0_REGION2_CTRL, 0x1, 16), .act_info = VOP_REG(RK3568_ESMART0_REGION2_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3568_ESMART0_REGION2_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3568_ESMART0_REGION2_DSP_ST, 0x1fff1fff, 0), @@ -689,6 +693,7 @@ static const struct vop2_win_regs rk3568_area3_data = { .enable = VOP_REG(RK3568_ESMART0_REGION3_CTRL, 0x1, 0), .format = VOP_REG(RK3568_ESMART0_REGION3_CTRL, 0x1f, 1), .rb_swap = VOP_REG(RK3568_ESMART0_REGION3_CTRL, 0x1, 14), + .uv_swap = VOP_REG(RK3568_ESMART0_REGION3_CTRL, 0x1, 16), .act_info = VOP_REG(RK3568_ESMART0_REGION3_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3568_ESMART0_REGION3_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3568_ESMART0_REGION3_DSP_ST, 0x1fff1fff, 0), @@ -729,6 +734,7 @@ static const struct vop2_win_regs rk3568_esmart_win_data = { .enable = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 0), .format = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1f, 1), .rb_swap = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 14), + .uv_swap = VOP_REG(RK3568_ESMART0_REGION0_CTRL, 0x1, 16), .act_info = VOP_REG(RK3568_ESMART0_REGION0_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3568_ESMART0_REGION0_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3568_ESMART0_REGION0_DSP_ST, 0x1fff1fff, 0),