From 8c59d20b75f0d9e492f9bc1b11fa8d8c1c154d63 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 28 Jan 2021 18:09:16 +0800 Subject: [PATCH] drm/rockchip: vop2: Add color key support Change-Id: Id32fc90b353f08cf575be57b1bcef137990bb183 Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 4 +- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 89 +++++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 2 + drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 1 + 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 251f44e9f0e0..76cb07cbaa66 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -515,8 +515,8 @@ struct vop2_win_regs { struct vop_reg alpha_mode; struct vop_reg alpha_en; struct vop_reg global_alpha_val; - struct vop_reg key_color; - struct vop_reg key_en; + struct vop_reg color_key; + struct vop_reg color_key_en; }; struct vop2_video_port_regs { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 785e2a61a0e4..e249e4547bcd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -132,6 +132,10 @@ #define VOP2_CLUSTER_YUV444_10 0x12 +#define VOP2_COLOR_KEY_NONE (0 << 31) +#define VOP2_COLOR_KEY_MASK (1 << 31) + + enum vop2_data_format { VOP2_FMT_ARGB8888 = 0, VOP2_FMT_RGB888, @@ -238,6 +242,7 @@ struct vop2_plane_state { int color_space; int global_alpha; int blend_mode; + int color_key; void *yrgb_kvaddr; unsigned long offset; int pdaf_data_type; @@ -314,6 +319,7 @@ struct vop2_win { struct drm_property *input_height_prop; struct drm_property *output_width_prop; struct drm_property *output_height_prop; + struct drm_property *color_key_prop; struct drm_property *scale_prop; struct drm_property *name_prop; }; @@ -2380,6 +2386,60 @@ static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_ spin_unlock(&vop2->reg_lock); } +/* + * The color key is 10 bit, so all format should + * convert to 10 bit here. + */ +static void vop2_plane_setup_color_key(struct drm_plane *plane) +{ + struct drm_plane_state *pstate = plane->state; + struct vop2_plane_state *vpstate = to_vop2_plane_state(pstate); + struct drm_framebuffer *fb = pstate->fb; + struct vop2_win *win = to_vop2_win(plane); + struct vop2 *vop2 = win->vop2; + uint32_t color_key_en = 0; + uint32_t color_key; + uint32_t r = 0; + uint32_t g = 0; + uint32_t b = 0; + + if (!(vpstate->color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) { + VOP_WIN_SET(vop2, win, color_key_en, 0); + return; + } + + switch (fb->format->format) { + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + r = (vpstate->color_key & 0xf800) >> 11; + g = (vpstate->color_key & 0x7e0) >> 5; + b = (vpstate->color_key & 0x1f); + r <<= 5; + g <<= 4; + b <<= 5; + color_key_en = 1; + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: + r = (vpstate->color_key & 0xff0000) >> 16; + g = (vpstate->color_key & 0xff00) >> 8; + b = (vpstate->color_key & 0xff); + r <<= 2; + g <<= 2; + b <<= 2; + color_key_en = 1; + break; + } + + color_key = (r << 20) || (g << 10) || b; + VOP_WIN_SET(vop2, win, color_key_en, color_key_en); + VOP_WIN_SET(vop2, win, color_key, color_key); +} + static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { struct drm_plane_state *pstate = plane->state; @@ -2559,7 +2619,7 @@ static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_plane_s } vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format); - + vop2_plane_setup_color_key(plane); VOP_WIN_SET(vop2, win, act_info, act_info); VOP_WIN_SET(vop2, win, dsp_info, dsp_info); VOP_WIN_SET(vop2, win, dsp_st, dsp_st); @@ -2794,6 +2854,7 @@ static int vop2_atomic_plane_set_property(struct drm_plane *plane, { struct rockchip_drm_private *private = plane->dev->dev_private; struct vop2_plane_state *vpstate = to_vop2_plane_state(state); + struct vop2_win *win = to_vop2_win(plane); if (property == private->eotf_prop) { vpstate->eotf = val; @@ -2810,6 +2871,11 @@ static int vop2_atomic_plane_set_property(struct drm_plane *plane, return 0; } + if (property == win->color_key_prop) { + vpstate->color_key = val; + return 0; + } + DRM_ERROR("failed to set vop2 plane property id:%d, name:%s\n", property->base.id, property->name); @@ -2823,6 +2889,7 @@ static int vop2_atomic_plane_get_property(struct drm_plane *plane, { struct rockchip_drm_private *private = plane->dev->dev_private; struct vop2_plane_state *vpstate = to_vop2_plane_state(state); + struct vop2_win *win = to_vop2_win(plane); if (property == private->eotf_prop) { *val = vpstate->eotf; @@ -2851,6 +2918,11 @@ static int vop2_atomic_plane_get_property(struct drm_plane *plane, } } + if (property == win->color_key_prop) { + *val = vpstate->color_key; + return 0; + } + DRM_ERROR("failed to get vop2 plane property id:%d, name:%s\n", property->base.id, property->name); @@ -5038,11 +5110,19 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned lon win->scale_prop = drm_property_create_range(vop2->drm_dev, DRM_MODE_PROP_IMMUTABLE, "SCALE_RATE", win->max_downscale_factor, win->max_upscale_factor); + /* + * Support 24 bit(RGB888) or 16 bit(rgb565) color key. + * Bit 31 is used as a flag to disable (0) or enable + * color keying (1). + */ + win->color_key_prop = drm_property_create_range(vop2->drm_dev, 0, "colorkey", 0, + 0x80ffffff); + if (!win->input_width_prop || !win->input_height_prop || !win->output_width_prop || !win->output_height_prop || - !win->scale_prop) { - DRM_ERROR("failed to create max_input/output property\n"); - return -EINVAL; + !win->scale_prop || !win->color_key_prop) { + DRM_ERROR("failed to create property\n"); + return -ENOMEM; } drm_object_attach_property(&win->base.base, win->input_width_prop, 0); @@ -5050,6 +5130,7 @@ static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned lon drm_object_attach_property(&win->base.base, win->output_width_prop, 0); drm_object_attach_property(&win->base.base, win->output_height_prop, 0); drm_object_attach_property(&win->base.base, win->scale_prop, 0); + drm_object_attach_property(&win->base.base, win->color_key_prop, 0); return 0; } diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 7ea242af0153..14e601249b2c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -945,6 +945,8 @@ static const struct vop2_win_regs rk3568_esmart_win_data = { .r2y_en = VOP_REG(RK3568_ESMART0_CTRL0, 0x1, 1), .csc_mode = VOP_REG(RK3568_ESMART0_CTRL0, 0x3, 2), .ymirror = VOP_REG(RK3568_ESMART0_CTRL1, 0x1, 31), + .color_key = VOP_REG(RK3568_ESMART0_COLOR_KEY_CTRL, 0x3fffffff, 0), + .color_key_en = VOP_REG(RK3366_LIT_WIN0_COLOR_KEY, 0x1, 31), }; /* diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index 8583cd977b52..67b2bd224735 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -1298,6 +1298,7 @@ #define RK3568_ESMART0_REGION3_SCL_FACTOR_YRGB 0x18C4 #define RK3568_ESMART0_REGION3_SCL_FACTOR_CBR 0x18C8 #define RK3568_ESMART0_REGION3_SCL_OFFSET 0x18CC +#define RK3568_ESMART0_COLOR_KEY_CTRL 0x18D0 #define RK3568_ESMART1_CTRL0 0x1A00 #define RK3568_ESMART1_CTRL1 0x1A04