diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index d78ec603cdf4..4104cc48a24e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -876,6 +876,14 @@ 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_reg grf_edp0_en; + struct vop_reg grf_edp1_en; + struct vop_reg grf_hdmi0_en; + struct vop_reg grf_hdmi1_en; + struct vop_reg grf_hdmi0_dsc_en; + struct vop_reg grf_hdmi1_dsc_en; + struct vop_reg grf_hdmi0_pin_pol; + struct vop_reg grf_hdmi1_pin_pol; }; struct vop_data { @@ -936,8 +944,10 @@ struct vop2_ctrl { struct vop_reg edp_pin_pol; struct vop_reg mipi_dclk_pol; struct vop_reg mipi_pin_pol; - struct vop_reg dp_dclk_pol; - struct vop_reg dp_pin_pol; + struct vop_reg dp0_dclk_pol; + struct vop_reg dp0_pin_pol; + struct vop_reg dp1_dclk_pol; + struct vop_reg dp1_pin_pol; /* This will be reference by win_phy_id */ struct vop_reg win_vp_id[16]; @@ -1030,7 +1040,10 @@ struct vop2_data { const struct vop2_power_domain_data *pd; const struct vop_csc_table *csc_table; const struct vop_hdr_table *hdr_table; - const struct vop_grf_ctrl *grf_ctrl; + const struct vop_grf_ctrl *sys_grf; + const struct vop_grf_ctrl *grf; + const struct vop_grf_ctrl *vo0_grf; + const struct vop_grf_ctrl *vo1_grf; struct vop_rect max_input; struct vop_rect max_output; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index d0bd7cc73545..3bf6ed7cdfa9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -120,10 +120,10 @@ #define VOP_WIN_TO_INDEX(vop2_win) \ ((vop2_win) - (vop2_win)->vop2->win) -#define VOP_GRF_SET(vop2, reg, v) \ +#define VOP_GRF_SET(vop2, grf, reg, v) \ do { \ - if (vop2->data->grf_ctrl) { \ - vop2_grf_writel(vop2, vop2->data->grf_ctrl->reg, v); \ + if (vop2->data->grf) { \ + vop2_grf_writel(vop2->grf, vop2->data->grf->reg, v); \ } \ } while (0) @@ -544,6 +544,12 @@ struct vop2_video_port { uint8_t nr_layers; int cursor_win_id; + /** + * @output_if: output connector attached to the video port, + * this flag is maintained in vop driver, updated in crtc_atomic_enable, + * cleared in crtc_atomic_disable; + */ + u32 output_if; /** * @active_tv_state: TV connector related states @@ -646,6 +652,9 @@ struct vop2 { uint32_t *regsbak; void __iomem *regs; struct regmap *grf; + struct regmap *sys_grf; + struct regmap *vo0_grf; + struct regmap *vo1_grf; /* physical map length of vop2 register */ uint32_t len; @@ -740,16 +749,16 @@ static void vop2_unlock(struct vop2 *vop2) mutex_unlock(&vop2->vop2_lock); } -static inline void vop2_grf_writel(struct vop2 *vop2, struct vop_reg reg, u32 v) +static inline void vop2_grf_writel(struct regmap *regmap, struct vop_reg reg, u32 v) { u32 val = 0; - if (IS_ERR_OR_NULL(vop2->grf)) + if (IS_ERR_OR_NULL(regmap)) return; if (reg.mask) { val = (v << reg.shift) | (reg.mask << (reg.shift + 16)); - regmap_write(vop2->grf, reg.offset, val); + regmap_write(regmap, reg.offset, val); } } @@ -3081,6 +3090,25 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, dsc->enabled = false; vcstate->dsc_enable = false; } + + if (vp->output_if & VOP_OUTPUT_IF_eDP0) + VOP_GRF_SET(vop2, grf, grf_edp0_en, 0); + + if (vp->output_if & VOP_OUTPUT_IF_eDP1) + VOP_GRF_SET(vop2, grf, grf_edp1_en, 0); + + if (vp->output_if & VOP_OUTPUT_IF_HDMI0) { + VOP_GRF_SET(vop2, grf, grf_hdmi0_dsc_en, 0); + VOP_GRF_SET(vop2, grf, grf_hdmi0_en, 0); + } + + if (vp->output_if & VOP_OUTPUT_IF_HDMI1) { + VOP_GRF_SET(vop2, grf, grf_hdmi1_dsc_en, 0); + VOP_GRF_SET(vop2, grf, grf_hdmi1_en, 0); + } + + vp->output_if = 0; + /* * Vop standby will take effect at end of current frame, * if dsp hold valid irq happen, it means standby complete. @@ -5278,6 +5306,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE); val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE); + vp->output_if = vcstate->output_if; + if (vcstate->output_if & VOP_OUTPUT_IF_RGB) { ret = vop2_calc_cru_cfg(crtc, VOP_OUTPUT_IF_RGB, &if_pixclk, &if_dclk); if (ret < 0) @@ -5285,7 +5315,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state VOP_CTRL_SET(vop2, rgb_en, 1); VOP_CTRL_SET(vop2, rgb_mux, vp_data->id); - VOP_GRF_SET(vop2, grf_dclk_inv, dclk_inv); + VOP_GRF_SET(vop2, sys_grf, grf_dclk_inv, dclk_inv); } if (vcstate->output_if & VOP_OUTPUT_IF_BT1120) { @@ -5296,7 +5326,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state 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); + VOP_GRF_SET(vop2, sys_grf, grf_bt1120_clk_inv, !dclk_inv); yc_swap = vop2_output_yc_swap(vcstate->bus_format); VOP_CTRL_SET(vop2, bt1120_yc_swap, yc_swap); } @@ -5308,7 +5338,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state 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); + VOP_GRF_SET(vop2, sys_grf, grf_bt656_clk_inv, !dclk_inv); yc_swap = vop2_output_yc_swap(vcstate->bus_format); VOP_CTRL_SET(vop2, bt656_yc_swap, yc_swap); } @@ -5387,6 +5417,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state VOP_CTRL_SET(vop2, edp0_mux, vp_data->id); VOP_CTRL_SET(vop2, edp_pin_pol, val); VOP_CTRL_SET(vop2, edp_dclk_pol, dclk_inv); + VOP_GRF_SET(vop2, grf, grf_edp0_en, 1); } if (vcstate->output_if & VOP_OUTPUT_IF_eDP1) { @@ -5402,6 +5433,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state VOP_CTRL_SET(vop2, edp1_mux, vp_data->id); VOP_CTRL_SET(vop2, edp_pin_pol, val); VOP_CTRL_SET(vop2, edp_dclk_pol, dclk_inv); + VOP_GRF_SET(vop2, grf, grf_edp1_en, 1); } if (vcstate->output_if & VOP_OUTPUT_IF_DP0) { @@ -5410,8 +5442,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state goto out; VOP_CTRL_SET(vop2, dp0_en, 1); VOP_CTRL_SET(vop2, dp0_mux, vp_data->id); - VOP_CTRL_SET(vop2, dp_dclk_pol, 0); - VOP_CTRL_SET(vop2, dp_pin_pol, val); + VOP_CTRL_SET(vop2, dp0_dclk_pol, 0); + VOP_CTRL_SET(vop2, dp0_pin_pol, val); } if (vcstate->output_if & VOP_OUTPUT_IF_DP1) { @@ -5421,8 +5453,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state VOP_CTRL_SET(vop2, dp1_en, 1); VOP_CTRL_SET(vop2, dp1_mux, vp_data->id); - VOP_CTRL_SET(vop2, dp_dclk_pol, 0); - VOP_CTRL_SET(vop2, dp_pin_pol, val); + VOP_CTRL_SET(vop2, dp1_dclk_pol, 0); + VOP_CTRL_SET(vop2, dp1_pin_pol, val); } if (vcstate->output_if & VOP_OUTPUT_IF_HDMI0) { @@ -5434,6 +5466,12 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state VOP_CTRL_SET(vop2, hdmi0_dclk_div, if_dclk->div_val); } + if (vcstate->dsc_enable) + VOP_GRF_SET(vop2, grf, grf_hdmi0_dsc_en, 1); + + VOP_GRF_SET(vop2, grf, grf_hdmi0_en, 1); + VOP_GRF_SET(vop2, vo1_grf, grf_hdmi0_pin_pol, val); + VOP_CTRL_SET(vop2, hdmi0_en, 1); VOP_CTRL_SET(vop2, hdmi0_en, 1); VOP_CTRL_SET(vop2, hdmi0_mux, vp_data->id); @@ -5451,6 +5489,12 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state VOP_CTRL_SET(vop2, hdmi1_dclk_div, if_dclk->div_val); } + if (vcstate->dsc_enable) + VOP_GRF_SET(vop2, grf, grf_hdmi1_dsc_en, 1); + + VOP_GRF_SET(vop2, grf, grf_hdmi1_en, 1); + VOP_GRF_SET(vop2, vo1_grf, grf_hdmi1_pin_pol, val); + VOP_CTRL_SET(vop2, hdmi1_en, 1); VOP_CTRL_SET(vop2, hdmi1_mux, vp_data->id); VOP_CTRL_SET(vop2, hdmi_pin_pol, val); @@ -7810,7 +7854,9 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(vop2->lut_regs); } - vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); + vop2->sys_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf"); + vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vop-grf"); + vop2->vo1_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,vo1-grf"); vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop"); if (IS_ERR(vop2->hclk)) { diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index c2f5ce23aab3..de2c78555a8e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -2288,7 +2288,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { }, }; -static const struct vop_grf_ctrl rk3568_grf_ctrl = { +static const struct vop_grf_ctrl rk3568_sys_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), @@ -2359,6 +2359,26 @@ static const struct vop2_ctrl rk3568_vop_ctrl = { .otp_en = VOP_REG(RK3568_OTP_WIN_EN, 0x1, 0), }; +static const struct vop_grf_ctrl rk3588_sys_grf_ctrl = { + .grf_bt656_clk_inv = VOP_REG(RK3588_GRF_SOC_CON1, 0x1, 14), + .grf_bt1120_clk_inv = VOP_REG(RK3588_GRF_SOC_CON1, 0x1, 14), + .grf_dclk_inv = VOP_REG(RK3588_GRF_SOC_CON1, 0x1, 14), +}; + +static const struct vop_grf_ctrl rk3588_vop_grf_ctrl = { + .grf_edp0_en = VOP_REG(RK3588_GRF_VOP_CON2, 0x1, 0), + .grf_hdmi0_en = VOP_REG(RK3588_GRF_VOP_CON2, 0x1, 1), + .grf_hdmi0_dsc_en = VOP_REG(RK3588_GRF_VOP_CON2, 0x1, 2), + .grf_edp1_en = VOP_REG(RK3588_GRF_VOP_CON2, 0x1, 3), + .grf_hdmi1_en = VOP_REG(RK3588_GRF_VOP_CON2, 0x1, 4), + .grf_hdmi1_dsc_en = VOP_REG(RK3588_GRF_VOP_CON2, 0x1, 4), +}; + +static const struct vop_grf_ctrl rk3588_vo1_grf_ctrl = { + .grf_hdmi0_pin_pol = VOP_REG(RK3588_GRF_VO1_CON0, 0x3, 5), + .grf_hdmi1_pin_pol = VOP_REG(RK3588_GRF_VO1_CON0, 0x3, 7), +}; + static const struct vop2_ctrl rk3588_vop_ctrl = { .cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15), .wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14), @@ -2414,11 +2434,14 @@ static const struct vop2_ctrl rk3588_vop_ctrl = { .mipi0_pixclk_div = VOP_REG(RK3568_DSP_IF_CTRL, 0x3, 24), .mipi1_pixclk_div = VOP_REG(RK3568_DSP_IF_CTRL, 0x3, 26), - .hdmi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 4), - .hdmi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 7), - .edp_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x3, 12), - .edp_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 15), - .mipi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 16), + /* HDMI pol control by GRF_VO1_CON0 + * DP0/1 clk pol is fixed + * MIPI/eDP pol is fixed + */ + .rgb_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 0), + .rgb_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 3), + .dp0_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 8), + .dp1_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 12), .mipi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 19), .win_vp_id[ROCKCHIP_VOP2_CLUSTER0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 16), .win_vp_id[ROCKCHIP_VOP2_CLUSTER1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 18), @@ -2447,7 +2470,7 @@ static const struct vop2_data rk3568_vop = { .max_input = { 4096, 2304 }, .max_output = { 4096, 2304 }, .ctrl = &rk3568_vop_ctrl, - .grf_ctrl = &rk3568_grf_ctrl, + .sys_grf = &rk3568_sys_grf_ctrl, .axi_intr = rk3568_vop_axi_intr, .nr_axi_intr = ARRAY_SIZE(rk3568_vop_axi_intr), .vp = rk3568_vop_video_ports, @@ -2470,6 +2493,9 @@ static const struct vop2_data rk3588_vop = { .max_input = { 8192, 4320 }, .max_output = { 4096, 2304 }, .ctrl = &rk3588_vop_ctrl, + .grf = &rk3588_vop_grf_ctrl, + .sys_grf = &rk3588_sys_grf_ctrl, + .vo1_grf = &rk3588_vo1_grf_ctrl, .axi_intr = rk3568_vop_axi_intr, .nr_axi_intr = ARRAY_SIZE(rk3568_vop_axi_intr), .dsc = rk3588_vop_dsc_data, diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index b8c866cb8322..b2000d083c54 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -1609,4 +1609,8 @@ #define RK3588_DSC_4K_STS0 0x41A8 #define RK3588_DSC_4K_ERS 0x41C4 +#define RK3588_GRF_SOC_CON1 0x0304 +#define RK3588_GRF_VOP_CON2 0x08 +#define RK3588_GRF_VO1_CON0 0x00 + #endif /* _ROCKCHIP_VOP_REG_H */