[PATCH 18/24] drm/msm/hdmi: cache is_hdmi instead of storing the connector

From: Dmitry Baryshkov

Date: Wed Jul 22 2026 - 02:49:44 EST


The HDMI driver stored the drm_connector in struct hdmi solely so that a
handful of call sites could consult connector->display_info.is_hdmi, and
so that the hotplug work could hand a connector to drm_bridge_detect().

Several of those call sites run outside of an atomic commit (the HPD
enable/disable paths in msm_hdmi_set_mode(), and the audio update path),
so they have no drm_atomic_state to derive the connector from and thus
relied on the stored pointer.

The only information actually consumed is the is_hdmi boolean. Cache it
in struct hdmi and refresh it from a new .hpd_notify bridge callback:
drm_bridge_connector_detect() updates the connector's EDID (and hence
display_info.is_hdmi) via drm_atomic_helper_connector_hdmi_hotplug()
before invoking .hpd_notify, so the cached value is always up to date.

With that, the stored connector becomes local to msm_hdmi_modeset_init():
the connector object is owned by the DRM core after creation, so there is
no need to keep a driver-side reference. The hotplug work now calls
msm_hdmi_bridge_detect() directly, which ignores its connector argument
anyway.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/hdmi/hdmi.c | 17 ++++++++---------
drivers/gpu/drm/msm/hdmi/hdmi.h | 4 +++-
drivers/gpu/drm/msm/hdmi/hdmi_audio.c | 2 +-
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 16 ++++++++++++++--
4 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 1d5a4b63f3c8..62961dddd8f5 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -27,7 +27,7 @@ void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
spin_lock_irqsave(&hdmi->reg_lock, flags);
if (power_on) {
ctrl |= HDMI_CTRL_ENABLE;
- if (!hdmi->connector->display_info.is_hdmi) {
+ if (!hdmi->is_hdmi) {
ctrl |= HDMI_CTRL_HDMI;
hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
ctrl &= ~HDMI_CTRL_HDMI;
@@ -164,6 +164,7 @@ static int msm_hdmi_modeset_init(struct msm_display *display,
struct drm_device *dev, struct drm_encoder *encoder)
{
struct hdmi *hdmi = container_of(display, struct hdmi, display);
+ struct drm_connector *connector = NULL;
int ret;

hdmi->dev = dev;
@@ -184,11 +185,11 @@ static int msm_hdmi_modeset_init(struct msm_display *display,
}
}

- hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);
- if (IS_ERR(hdmi->connector)) {
- ret = PTR_ERR(hdmi->connector);
+ connector = drm_bridge_connector_init(hdmi->dev, encoder);
+ if (IS_ERR(connector)) {
+ ret = PTR_ERR(connector);
DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", ret);
- hdmi->connector = NULL;
+ connector = NULL;
goto fail;
}

@@ -204,10 +205,8 @@ static int msm_hdmi_modeset_init(struct msm_display *display,
return 0;

fail:
- if (hdmi->connector) {
- hdmi->connector->funcs->destroy(hdmi->connector);
- hdmi->connector = NULL;
- }
+ if (connector)
+ connector->funcs->destroy(connector);

return ret;
}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 869f55d4704a..d4adaa6ccdd5 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -47,6 +47,9 @@ struct hdmi {
struct mutex state_mutex; /* protects two booleans */
unsigned long pixclock;

+ /* cached from the connector's EDID, updated on hotplug */
+ bool is_hdmi;
+
void __iomem *mmio;
phys_addr_t mmio_size;
void __iomem *qfprom_mmio;
@@ -62,7 +65,6 @@ struct hdmi {
struct device *phy_dev;

struct i2c_adapter *i2c;
- struct drm_connector *connector;
struct drm_bridge *bridge;

struct drm_bridge *next_bridge;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
index 249c167ab04d..ce1864f3f659 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c
@@ -19,7 +19,7 @@ int msm_hdmi_audio_update(struct hdmi *hdmi)
bool enabled = audio->enabled;
u32 acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl, audio_config;

- if (!hdmi->connector->display_info.is_hdmi)
+ if (!hdmi->is_hdmi)
return -EINVAL;

DBG("audio: enabled=%d, channels=%d, rate=%d",
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index 7abb9243dba5..84a423af73e9 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -345,7 +345,7 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
if (hdmi->power_on) {
power_off(bridge);
hdmi->power_on = false;
- if (hdmi->connector->display_info.is_hdmi)
+ if (hdmi->is_hdmi)
msm_hdmi_audio_update(hdmi);
msm_hdmi_phy_resource_disable(phy);
}
@@ -452,6 +452,17 @@ static enum drm_mode_status msm_hdmi_bridge_tmds_char_rate_valid(const struct dr
return 0;
}

+static void msm_hdmi_bridge_hpd_notify(struct drm_bridge *bridge,
+ struct drm_connector *connector,
+ enum drm_connector_status status)
+{
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
+
+ /* called after the EDID update, so display_info is up to date */
+ hdmi->is_hdmi = connector->display_info.is_hdmi;
+}
+
static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
@@ -460,6 +471,7 @@ static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
.atomic_post_disable = msm_hdmi_bridge_atomic_post_disable,
.edid_read = msm_hdmi_bridge_edid_read,
.detect = msm_hdmi_bridge_detect,
+ .hpd_notify = msm_hdmi_bridge_hpd_notify,
.hpd_enable = msm_hdmi_hpd_enable,
.hpd_disable = msm_hdmi_hpd_disable,
.hdmi_tmds_char_rate_valid = msm_hdmi_bridge_tmds_char_rate_valid,
@@ -482,7 +494,7 @@ msm_hdmi_hotplug_work(struct work_struct *work)
container_of(work, struct hdmi_bridge, hpd_work);
struct drm_bridge *bridge = &hdmi_bridge->base;

- drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge, hdmi_bridge->hdmi->connector));
+ drm_bridge_hpd_notify(bridge, msm_hdmi_bridge_detect(bridge, NULL));
}

/* initialize bridge */

--
2.47.3