mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
drm/rockchip: vop2: Add VOP_GRF and SYS_GRF support
Some clk invert(dclk invert) control in SYS_GRF Some interface enable(hdmi/edp enable) control in VOP_GRF hdmi_vsync/hsync_pol control in VO1_GRF Signed-off-by: Andy Yan <andy.yan@rock-chips.com> Change-Id: Ia3972c9d207c9385b4512c96ea8e2d66e8fa03d5
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user