diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index cd941b6aa404..02c6f3f1a620 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -508,6 +508,7 @@ struct vop2_video_port_regs { struct vop_reg out_mode; struct vop_reg standby; struct vop_reg dsp_interlace; + struct vop_reg dsp_filed_pol; struct vop_reg dsp_data_swap; struct vop_reg pre_scan_htiming; struct vop_reg htotal_pw; @@ -648,6 +649,8 @@ struct vop2_layer_data { struct vop_grf_ctrl { struct vop_reg grf_dclk_inv; + struct vop_reg grf_bt1120_clk_inv; + struct vop_reg grf_bt656_clk_inv; }; struct vop_data { @@ -734,6 +737,9 @@ struct vop2_ctrl { struct vop_reg dst_alpha_ctrl; struct vop_reg bt1120_yc_swap; + struct vop_reg bt1120_uv_swap; + struct vop_reg bt656_yc_swap; + struct vop_reg bt656_uv_swap; struct vop_reg reg_done_frm; struct vop_reg cfg_done; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index d16ed5de3d34..b919e9670cf2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -790,15 +790,32 @@ static bool vop2_output_uv_swap(uint32_t bus_format, uint32_t output_mode) * * From H/W testing, YUV444 mode need a rb swap. */ - if ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || - bus_format == MEDIA_BUS_FMT_YUV10_1X30) && - (output_mode == ROCKCHIP_OUT_MODE_AAAA || - output_mode == ROCKCHIP_OUT_MODE_P888)) + if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 || + bus_format == MEDIA_BUS_FMT_VYUY8_1X16 || + bus_format == MEDIA_BUS_FMT_YVYU8_2X8 || + bus_format == MEDIA_BUS_FMT_VYUY8_2X8 || + ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 || + bus_format == MEDIA_BUS_FMT_YUV10_1X30) && + (output_mode == ROCKCHIP_OUT_MODE_AAAA || + output_mode == ROCKCHIP_OUT_MODE_P888))) return true; else return false; } +static bool vop2_output_yc_swap(uint32_t bus_format) +{ + switch (bus_format) { + case MEDIA_BUS_FMT_YUYV8_1X16: + case MEDIA_BUS_FMT_YVYU8_1X16: + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YVYU8_2X8: + return true; + default: + return false; + } +} + static bool is_yuv_support(uint32_t format) { switch (format) { @@ -823,7 +840,13 @@ static bool is_yuv_output(uint32_t bus_format) case MEDIA_BUS_FMT_UYYVYY8_0_5X24: case MEDIA_BUS_FMT_UYYVYY10_0_5X30: case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YVYU8_2X8: + case MEDIA_BUS_FMT_UYVY8_2X8: + case MEDIA_BUS_FMT_VYUY8_2X8: case MEDIA_BUS_FMT_YUYV8_1X16: + case MEDIA_BUS_FMT_YVYU8_1X16: + case MEDIA_BUS_FMT_UYVY8_1X16: + case MEDIA_BUS_FMT_VYUY8_1X16: return true; default: return false; @@ -2635,7 +2658,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state int sys_status = SYS_STATUS_LCDC0; uint8_t out_mode; int for_ddr_freq = 0; - bool dclk_inv; + bool dclk_inv, yc_swap = false, uv_swap = false; int act_end; uint32_t val; @@ -2666,13 +2689,24 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state } if (vcstate->output_if & VOP_OUTPUT_IF_BT1120) { + VOP_CTRL_SET(vop2, rgb_en, 1); VOP_CTRL_SET(vop2, bt1120_en, 1); VOP_CTRL_SET(vop2, rgb_mux, vp_data->id); + VOP_GRF_SET(vop2, grf_bt1120_clk_inv, !dclk_inv); + yc_swap = vop2_output_yc_swap(vcstate->bus_format); + uv_swap = vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode); + VOP_CTRL_SET(vop2, bt1120_yc_swap, yc_swap); + VOP_CTRL_SET(vop2, bt1120_uv_swap, uv_swap); } if (vcstate->output_if & VOP_OUTPUT_IF_BT656) { VOP_CTRL_SET(vop2, bt656_en, 1); VOP_CTRL_SET(vop2, rgb_mux, vp_data->id); + VOP_GRF_SET(vop2, grf_bt656_clk_inv, !dclk_inv); + yc_swap = vop2_output_yc_swap(vcstate->bus_format); + uv_swap = vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode); + VOP_CTRL_SET(vop2, bt656_yc_swap, yc_swap); + VOP_CTRL_SET(vop2, bt656_uv_swap, uv_swap); } if (vcstate->output_if & VOP_OUTPUT_IF_LVDS0) { @@ -2802,11 +2836,13 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state val = vtotal << 16 | (vtotal + vsync_len); VOP_MODULE_SET(vop2, vp, vs_st_end_f1, val); VOP_MODULE_SET(vop2, vp, dsp_interlace, 1); + VOP_MODULE_SET(vop2, vp, dsp_filed_pol, 1); VOP_MODULE_SET(vop2, vp, p2i_en, 1); vtotal += vtotal + 1; act_end = vact_end_f1; } else { VOP_MODULE_SET(vop2, vp, dsp_interlace, 0); + VOP_MODULE_SET(vop2, vp, dsp_filed_pol, 0); VOP_MODULE_SET(vop2, vp, p2i_en, 0); act_end = vact_end; } diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index 094386eae88d..642b739a9469 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -355,6 +355,7 @@ static const struct vop2_video_port_regs rk3568_vop_vp0_regs = { .standby = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 31), .core_dclk_div = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 4), .p2i_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 5), + .dsp_filed_pol = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 6), .dsp_interlace = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 7), .dsp_data_swap = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1f, 8), .pre_scan_htiming = VOP_REG(RK3568_VP0_PRE_SCAN_HTIMING, 0x1fff1fff, 0), @@ -411,6 +412,7 @@ static const struct vop2_video_port_regs rk3568_vop_vp1_regs = { .standby = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 31), .core_dclk_div = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 4), .p2i_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 5), + .dsp_filed_pol = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 6), .dsp_interlace = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 7), .dsp_data_swap = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1f, 8), .pre_scan_htiming = VOP_REG(RK3568_VP1_PRE_SCAN_HTIMING, 0x1fff1fff, 0), @@ -442,6 +444,7 @@ static const struct vop2_video_port_regs rk3568_vop_vp2_regs = { .standby = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 31), .core_dclk_div = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 4), .p2i_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 5), + .dsp_filed_pol = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 6), .dsp_interlace = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 7), .dsp_data_swap = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1f, 8), .pre_scan_htiming = VOP_REG(RK3568_VP2_PRE_SCAN_HTIMING, 0x1fff1fff, 0), @@ -928,6 +931,8 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { }; static const struct vop_grf_ctrl rk3568_grf_ctrl = { + .grf_bt656_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 1), + .grf_bt1120_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 2), .grf_dclk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 3), }; @@ -964,6 +969,10 @@ static const struct vop2_ctrl rk3568_vop_ctrl = { .lvds_dual_en = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 0), .lvds_dual_mode = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 1), .lvds_dual_channel_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 2), + .bt656_uv_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 4), + .bt656_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 5), + .bt1120_uv_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 8), + .bt1120_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 9), .lvds_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 0), .lvds_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 3), .hdmi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 4),