inno_hdmi_init_hw() drives the register interface from the system clock on every platform, by setting v_REG_CLK_SOURCE_SYS unconditionally in HDMI_SYS_CTRL.
That is not right everywhere. On the JH7110 a Framework 13 (fml13v01) panel flickers continuously with the system clock selected and behaves once the TMDS clock drives the register interface instead. Maud Spierings found this by diffing HDMI_SYS_CTRL against the StarFive vendor kernel, which leaves the bit clear. Add a plat_data flag for it rather than changing the bit for everyone. The Rockchip integrations keep the system clock, so this is a no-op for them; only a platform that asks for it gets the TMDS clock. Reported-by: Maud Spierings <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Tested-by: Maud Spierings <[email protected]> Tested-by: Byron Stanoszek <[email protected]> Tested-by: OOHehir <[email protected]> Signed-off-by: Michal Wilczynski <[email protected]> --- drivers/gpu/drm/bridge/inno-hdmi.c | 4 +++- include/drm/bridge/inno_hdmi.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/inno-hdmi.c b/drivers/gpu/drm/bridge/inno-hdmi.c index 42a3cd450e0f56a0b06d187645522624feb8918d..66e7e08f89813b4ddcb38a3d0b296132944f06bb 100644 --- a/drivers/gpu/drm/bridge/inno-hdmi.c +++ b/drivers/gpu/drm/bridge/inno-hdmi.c @@ -580,7 +580,9 @@ static void inno_hdmi_init_hw(struct inno_hdmi *hdmi) usleep_range(100, 150); msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL; - val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH; + val = v_REG_CLK_INV | v_PWR_ON | v_INT_POL_HIGH; + val |= hdmi->plat_data->reg_clk_source_tmds ? v_REG_CLK_SOURCE_TMDS : + v_REG_CLK_SOURCE_SYS; hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val); inno_hdmi_standby(hdmi); diff --git a/include/drm/bridge/inno_hdmi.h b/include/drm/bridge/inno_hdmi.h index 790633fcea97a6b9840da7b19a0c0b0d7271fb83..cc5099d05f641eef5de91ed5becde7337c04b013 100644 --- a/include/drm/bridge/inno_hdmi.h +++ b/include/drm/bridge/inno_hdmi.h @@ -32,6 +32,8 @@ struct inno_hdmi_plat_data { const struct inno_hdmi_plat_ops *ops; struct inno_hdmi_phy_config *phy_configs; struct inno_hdmi_phy_config *default_phy_config; + /* Clock the register interface from the TMDS clock, not the system clock. */ + bool reg_clk_source_tmds; }; struct inno_hdmi *inno_hdmi_bind(struct platform_device *pdev, -- 2.34.1
