[PATCH RFC/DO NOT MERGE 07/12] drm/msm/hdmi: Split PHY init from power up
From: Krzysztof Kozlowski
Date: Fri Aug 28 2026 - 10:13:42 EST
Future Eliza SoC HDMI PHY and HDMI block require certain clock
operations, like reparenting pixclok to HDMI PHY PLL, once PHY is
initialized. Similarly to what is happening on Qualcomm MSM DSI blocks
since SM8750.
Rework and split the HDMI msm_hdmi_power_on() into smaller steps:
1. Leave untouched logic related to runtime PM (power on the domain).
This is done only once, guarded by "if (hdmi->power_on) {" condition,
2. During every msm_hdmi_bridge_atomic_pre_enable(), initialize the HDMI
PHY with new msm_hdmi_phy_init() as it was previously powered down.
Currently no-op for all the PHYs,
3. Similarly, for every enable prepare and set rate of HDMI pixclock
(extp_clk). This will also reparent the pixclock to HDMI PHY PLL
later and should happen after the HDMI PHY is initialized (point 2
above).
Commit should have no practical impact on existing devices.
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/hdmi/hdmi.h | 4 ++++
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 30 +++++++++++++++++++++++++-----
drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 16 ++++++++++++++++
3 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 436d4f9fe346..306b988bca72 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -151,6 +151,8 @@ enum hdmi_phy_type {
struct hdmi_phy_cfg {
enum hdmi_phy_type type;
+ void (*init)(struct hdmi_phy *phy, unsigned long pixclock);
+ void (*deinit)(struct hdmi_phy *phy);
void (*powerup)(struct hdmi_phy *phy, unsigned long pixclock);
void (*powerdown)(struct hdmi_phy *phy);
const char * const *reg_names;
@@ -186,6 +188,8 @@ static inline u32 hdmi_phy_read(struct hdmi_phy *phy, u32 reg)
int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy);
void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy);
+void msm_hdmi_phy_init(struct hdmi_phy *phy, unsigned long pixclock);
+void msm_hdmi_phy_deinit(struct hdmi_phy *phy);
void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long pixclock);
void msm_hdmi_phy_powerdown(struct hdmi_phy *phy);
void __init msm_hdmi_phy_driver_register(void);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index a5f891661ea3..d0e3b27644fe 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -14,14 +14,20 @@
#include "hdmi.h"
static void msm_hdmi_power_on(struct drm_bridge *bridge)
+{
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
+
+ pm_runtime_resume_and_get(&hdmi->pdev->dev);
+}
+
+static void msm_hdmi_clk_prepare(struct drm_bridge *bridge)
{
struct drm_device *dev = bridge->dev;
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = hdmi_bridge->hdmi;
int ret;
- pm_runtime_resume_and_get(&hdmi->pdev->dev);
-
if (hdmi->extp_clk) {
DBG("pixclock: %lu", hdmi->pixclock);
ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock);
@@ -44,10 +50,16 @@ static void power_off(struct drm_bridge *bridge)
*/
mdelay(16 + 4);
+ pm_runtime_put(&hdmi->pdev->dev);
+}
+
+static void msm_hdmi_clk_unprepare(struct drm_bridge *bridge)
+{
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
+
if (hdmi->extp_clk)
clk_disable_unprepare(hdmi->extp_clk);
-
- pm_runtime_put(&hdmi->pdev->dev);
}
#define AVI_IFRAME_LINE_NUMBER 1
@@ -300,8 +312,14 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
+ msm_hdmi_phy_init(phy, hdmi->pixclock);
+ /*
+ * Re-parent clocks and set rates once phy is properly initialized.
+ * OTOH, TX DATA on the phy should not be enabled before clocks are
+ * configured.
+ */
+ msm_hdmi_clk_prepare(bridge);
msm_hdmi_phy_powerup(phy, hdmi->pixclock);
-
msm_hdmi_set_mode(hdmi, true);
if (hdmi->hdcp_ctrl)
@@ -325,6 +343,8 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
msm_hdmi_set_mode(hdmi, hdmi->hpd_enabled);
msm_hdmi_phy_powerdown(phy);
+ msm_hdmi_clk_unprepare(bridge);
+ msm_hdmi_phy_deinit(phy);
if (hdmi->power_on) {
power_off(bridge);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
index eb1088755cb3..8ce87d9adf74 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
@@ -94,6 +94,22 @@ void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy)
pm_runtime_put_sync(dev);
}
+void msm_hdmi_phy_init(struct hdmi_phy *phy, unsigned long pixclock)
+{
+ if (!phy || !phy->cfg->init)
+ return;
+
+ phy->cfg->init(phy, pixclock);
+}
+
+void msm_hdmi_phy_deinit(struct hdmi_phy *phy)
+{
+ if (!phy || !phy->cfg->deinit)
+ return;
+
+ phy->cfg->deinit(phy);
+}
+
void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long pixclock)
{
if (!phy || !phy->cfg->powerup)
--
2.53.0