drm/msm/hdmi: ensure that HDMI is up if HPD is requested

The HDMI block needs to be enabled to properly generate HPD events. Make
sure it is not turned off in the disable paths if HPD delivery is enabled.

Reviewed-by: Jessica Zhang <quic_jesszhan@quicinc.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Patchwork: https://patchwork.freedesktop.org/patch/651722/
Link: https://lore.kernel.org/r/20250505-fd-hdmi-hpd-v5-12-48541f76318c@oss.qualcomm.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
This commit is contained in:
Dmitry Baryshkov 2025-05-05 03:14:56 +03:00 committed by Dmitry Baryshkov
parent 969bbbf7fb
commit b93f19d8d0
4 changed files with 18 additions and 2 deletions

View File

@ -293,6 +293,7 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev)
hdmi->pdev = pdev;
hdmi->config = config;
spin_lock_init(&hdmi->reg_lock);
mutex_init(&hdmi->state_mutex);
ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge);
if (ret && ret != -ENODEV)

View File

@ -41,6 +41,8 @@ struct hdmi {
/* video state: */
bool power_on;
bool hpd_enabled;
struct mutex state_mutex; /* protects two booleans */
unsigned long int pixclock;
void __iomem *mmio;

View File

@ -302,11 +302,13 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
msm_hdmi_set_timings(hdmi, &crtc_state->adjusted_mode);
mutex_lock(&hdmi->state_mutex);
if (!hdmi->power_on) {
msm_hdmi_phy_resource_enable(phy);
msm_hdmi_power_on(bridge);
hdmi->power_on = true;
}
mutex_unlock(&hdmi->state_mutex);
if (connector->display_info.is_hdmi)
msm_hdmi_audio_update(hdmi);
@ -332,7 +334,10 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
msm_hdmi_hdcp_off(hdmi->hdcp_ctrl);
DBG("power down");
msm_hdmi_set_mode(hdmi, false);
/* Keep the HDMI enabled if the HPD is enabled */
mutex_lock(&hdmi->state_mutex);
msm_hdmi_set_mode(hdmi, hdmi->hpd_enabled);
msm_hdmi_phy_powerdown(phy);
@ -343,6 +348,7 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
msm_hdmi_audio_update(hdmi);
msm_hdmi_phy_resource_disable(phy);
}
mutex_unlock(&hdmi->state_mutex);
}
static void msm_hdmi_set_timings(struct hdmi *hdmi,

View File

@ -76,10 +76,14 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
if (ret)
return ret;
mutex_lock(&hdmi->state_mutex);
msm_hdmi_set_mode(hdmi, false);
msm_hdmi_phy_reset(hdmi);
msm_hdmi_set_mode(hdmi, true);
hdmi->hpd_enabled = true;
mutex_unlock(&hdmi->state_mutex);
hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b);
/* enable HPD events: */
@ -109,7 +113,10 @@ void msm_hdmi_hpd_disable(struct hdmi *hdmi)
/* Disable HPD interrupt */
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
msm_hdmi_set_mode(hdmi, false);
mutex_lock(&hdmi->state_mutex);
hdmi->hpd_enabled = false;
msm_hdmi_set_mode(hdmi, hdmi->power_on);
mutex_unlock(&hdmi->state_mutex);
pm_runtime_put(dev);
}