From ffa6d4f255f6843fb75c4e317b0af157343811aa Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Wed, 1 Jun 2022 21:57:14 +0800 Subject: [PATCH] drm/rockchip: vop: add support for cvbs interface on rk3036 CVBS only support for 480i and 576i display mode. It is needed for rk3036 to enable scaling when using interlace mode, which also updated in this commit. Signed-off-by: Damon Ding Change-Id: I1d131ec71c0b31680280353e1690f8c01eb3c94e --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 17 ++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 1 + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 10 ++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 9cbb35c289de..d7ea1f80ea12 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -826,11 +826,22 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win *win, uint16_t lb_mode; uint32_t val; const struct vop_data *vop_data = vop->data; + struct drm_display_mode *adjusted_mode = &vop->rockchip_crtc.crtc.state->adjusted_mode; int vskiplines; if (!win->phy->scl) return; + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) { + VOP_SCL_SET(vop, win, scale_yrgb_x, ((src_w << 12) / dst_w)); + VOP_SCL_SET(vop, win, scale_yrgb_y, ((src_h << 12) / dst_h)); + if (is_yuv) { + VOP_SCL_SET(vop, win, scale_cbcr_x, ((cbcr_src_w << 12) / dst_w)); + VOP_SCL_SET(vop, win, scale_cbcr_y, ((cbcr_src_h << 12) / dst_h)); + } + return; + } + if (!(vop_data->feature & VOP_FEATURE_ALPHA_SCALE)) { if (is_alpha_support(pixel_format) && (src_w != dst_w || src_h != dst_h)) @@ -2011,6 +2022,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, dsp_h = 4; actual_h = dsp_h * actual_h / drm_rect_height(dest); } + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) + dsp_h = dsp_h / 2; act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff); @@ -2019,6 +2032,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane, dsp_stx = dest->x1 + mode->crtc_htotal - mode->crtc_hsync_start; dsp_sty = dest->y1 + mode->crtc_vtotal - mode->crtc_vsync_start; + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) && vop->version == VOP_VERSION(2, 2)) + dsp_sty = dest->y1 / 2 + mode->crtc_vtotal - mode->crtc_vsync_start; dsp_st = dsp_sty << 16 | (dsp_stx & 0xffff); s = to_rockchip_crtc_state(crtc->state); @@ -2046,7 +2061,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, if (win->phy->scl) scl_vop_cal_scl_fac(vop, win, actual_w, actual_h, - drm_rect_width(dest), drm_rect_height(dest), + drm_rect_width(dest), dsp_h, fb->format->format); if (VOP_WIN_SUPPORT(vop, win, color_key)) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index bedf2a99a793..280faffeded9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -254,6 +254,7 @@ struct vop_ctrl { struct vop_reg post_scl_factor; struct vop_reg post_scl_ctrl; struct vop_reg dsp_interlace; + struct vop_reg dsp_interlace_pol; struct vop_reg global_regdone_en; struct vop_reg auto_gate_en; struct vop_reg post_lb_mode; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index ba43530af653..e47f5e865537 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -1239,19 +1239,27 @@ static const struct vop_intr rk3036_intr = { static const struct vop_ctrl rk3036_ctrl_data = { .standby = VOP_REG(RK3036_SYS_CTRL, 0x1, 30), + .sw_dac_sel = VOP_REG(RK3036_SYS_CTRL, 0x1, 29), .out_mode = VOP_REG(RK3036_DSP_CTRL0, 0xf, 0), + .dsp_interlace = VOP_REG(RK3036_DSP_CTRL0, 0x1, 12), .dsp_blank = VOP_REG(RK3036_DSP_CTRL1, 0x1, 24), + .dsp_background = VOP_REG(RK3036_DSP_CTRL1, 0xffffff, 0), .dclk_pol = VOP_REG(RK3036_DSP_CTRL0, 0x1, 7), .pin_pol = VOP_REG(RK3036_DSP_CTRL0, 0x7, 4), .dither_down_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 27), + .tve_sw_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 25), + .dsp_interlace_pol = VOP_REG(RK3036_DSP_CTRL0, 0x1, 13), .dither_down_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3036_DSP_CTRL0, 0x1, 10), .dither_up_en = VOP_REG(RK3036_DSP_CTRL0, 0x1, 9), .dsp_layer_sel = VOP_REG(RK3036_DSP_CTRL0, 0x1, 8), .htotal_pw = VOP_REG(RK3036_DSP_HTOTAL_HS_END, 0x1fff1fff, 0), .hact_st_end = VOP_REG(RK3036_DSP_HACT_ST_END, 0x1fff1fff, 0), + .tve_dclk_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 20), + .tve_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 21), .hdmi_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 22), .hdmi_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 23), + .core_dclk_div = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 30), .hdmi_pin_pol = VOP_REG(RK3036_INT_SCALER, 0x7, 4), .rgb_en = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 24), .rgb_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 25), @@ -1261,6 +1269,8 @@ static const struct vop_ctrl rk3036_ctrl_data = { .mipi_dclk_pol = VOP_REG(RK3036_AXI_BUS_CTRL, 0x1, 29), .vtotal_pw = VOP_REG(RK3036_DSP_VTOTAL_VS_END, 0x1fff1fff, 0), .vact_st_end = VOP_REG(RK3036_DSP_VACT_ST_END, 0x1fff1fff, 0), + .vs_st_end_f1 = VOP_REG(RK3036_DSP_VS_ST_END_F1, 0x1fff1fff, 0), + .vact_st_end_f1 = VOP_REG(RK3036_DSP_VACT_ST_END_F1, 0x1fff1fff, 0), .cfg_done = VOP_REG(RK3036_REG_CFG_DONE, 0x1, 0), };