drm/rockchip: dw_hdmi: Introduce hdmiphy-pll clock

If drm bind takes too long when entering the kernel,
for example, retry reading edid. When the clock is not
enabled, it will closed by rockchip_clocks_loader_unprotect().
Therefore, if the uboot logo is displayed, hdmi needs to
enable hdmiphy pll when hdmi bind.

Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
Change-Id: I908f3f23bd60535d01399c972ae0942e6abe3dd4
This commit is contained in:
Algea Cao
2023-04-03 19:32:31 +08:00
committed by Tao Huang
parent da99936dc2
commit 135b065009
3 changed files with 35 additions and 0 deletions

View File

@ -3482,6 +3482,8 @@ static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
handle_plugged_change(hdmi, false);
dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
if (hdmi->plat_data->dclk_set)
hdmi->plat_data->dclk_set(hdmi->plat_data->phy_data, false, 0);
mutex_unlock(&hdmi->mutex);
mutex_lock(&hdmi->i2c->lock);
@ -3496,6 +3498,8 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
mutex_lock(&hdmi->mutex);
hdmi->disabled = false;
if (hdmi->plat_data->dclk_set)
hdmi->plat_data->dclk_set(hdmi->plat_data->phy_data, true, 0);
dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
handle_plugged_change(hdmi, true);
@ -4285,6 +4289,8 @@ __dw_hdmi_probe(struct platform_device *pdev,
hdmi->initialized = true;
if (hdmi->plat_data->set_ddc_io)
hdmi->plat_data->set_ddc_io(hdmi->plat_data->phy_data, true);
if (hdmi->plat_data->dclk_set)
hdmi->plat_data->dclk_set(hdmi->plat_data->phy_data, true, 0);
} else if (ret & HDMI_PHY_TX_PHY_LOCK) {
hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
if (hdmi->plat_data->set_ddc_io)

View File

@ -128,6 +128,7 @@ struct rockchip_hdmi {
struct clk *grf_clk;
struct clk *hclk_vio;
struct clk *hclk_vop;
struct clk *dclk_vop;
struct dw_hdmi *hdmi;
struct phy *phy;
@ -646,6 +647,12 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
return PTR_ERR(hdmi->hclk_vop);
}
hdmi->dclk_vop = devm_clk_get_optional(hdmi->dev, "dclk_vop");
if (IS_ERR(hdmi->dclk_vop)) {
dev_err(hdmi->dev, "failed to get dclk_vop\n");
return PTR_ERR(hdmi->dclk_vop);
}
ret = of_property_read_u32(np, "max-tmdsclk",
&hdmi->max_tmdsclk);
if (ret != -EINVAL && ret < 0) {
@ -1302,6 +1309,25 @@ static void dw_hdmi_rockchip_set_ddc_io(void *data, bool enable)
}
}
static int dw_hdmi_rockchip_dclk_set(void *data, bool enable, int vp_id)
{
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
int ret = 0;
if (!hdmi->dclk_vop)
return 0;
if (enable) {
ret = clk_prepare_enable(hdmi->dclk_vop);
if (ret < 0)
dev_err(hdmi->dev, "failed to enable dclk_vop\n");
} else {
clk_disable_unprepare(hdmi->dclk_vop);
}
return ret;
}
static const struct drm_prop_enum_list color_depth_enum_list[] = {
{ 0, "Automatic" }, /* Prefer highest color depth */
{ 8, "24bit" },
@ -1981,6 +2007,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
dw_hdmi_rockchip_set_prev_bus_format;
plat_data->set_ddc_io =
dw_hdmi_rockchip_set_ddc_io;
plat_data->dclk_set =
dw_hdmi_rockchip_dclk_set;
plat_data->property_ops = &dw_hdmi_rockchip_property_ops;
encoder = &hdmi->encoder;

View File

@ -184,6 +184,7 @@ struct dw_hdmi_plat_data {
bool (*check_hdr_color_change)(struct drm_connector_state *conn_state, void *data);
void (*set_prev_bus_format)(void *data, unsigned long bus_format);
void (*set_ddc_io)(void *data, bool enable);
int (*dclk_set)(void *data, bool enable, int vp_id);
/* Vendor Property support */
const struct dw_hdmi_property_ops *property_ops;