mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
To: Rob Clark <robin.clark@oss.qualcomm.com>,
	Dmitry Baryshkov <lumag@kernel.org>,
	Abhinav Kumar <abhinav.kumar@linux.dev>,
	Jessica Zhang <jesszhan0024@gmail.com>,
	Sean Paul <sean@poorly.run>,
	Marijn Suijten <marijn.suijten@somainline.org>,
	David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
	Andrzej Hajda <andrzej.hajda@intel.com>,
	Neil Armstrong <neil.armstrong@linaro.org>,
	Robert Foss <rfoss@kernel.org>,
	Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
	Jonas Karlman <jonas@kwiboo.se>,
	Jernej Skrabec <jernej.skrabec@gmail.com>,
	Luca Ceresoli <luca.ceresoli@bootlin.com>,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Maxime Ripard <mripard@kernel.org>,
	Thomas Zimmermann <tzimmermann@suse.de>
Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
	freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: [PATCH 22/24] drm/msm/dp: stop storing the connector in struct msm_dp
Date: Wed, 22 Jul 2026 09:36:37 +0300	[thread overview]
Message-ID: <20260722-drm-msm-display-interface-v1-22-368c10fe62fd@oss.qualcomm.com> (raw)
In-Reply-To: <20260722-drm-msm-display-interface-v1-0-368c10fe62fd@oss.qualcomm.com>

struct msm_dp cached the drm_connector so that the asynchronous HPD
handlers, the YUV-420 query and debugfs could reach it. Keeping this
pointer means any common code that creates the connector has to hand it
back to the DP sub-block, and it couples the sub-block to a connector it
does not own.

Every consumer can instead obtain the connector from a context that
already has it:

 - the HPD handler chain (plug/unplug/irq -> process_hpd_high,
   handle_plugged_change) is only ever entered from the bridge
   .hpd_notify callback and the atomic enable/post_disable callbacks,
   all of which carry (or can derive from the atomic state) the
   connector; thread it through;

 - the .is_yuv_mode op is called from the DPU encoder, which already
   fetches the connector from the atomic state - pass it in;

 - .needs_periph_flush is evaluated at flush time, after ->mode_set()
   has cached the result in msm_dp_mode.out_fmt_is_yuv_420, so read the
   cached flag rather than the live connector;

 - debugfs only needs a connector to report status, so look it up from
   the sub-block's encoder.

With that, drop the stored connector.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
 drivers/gpu/drm/msm/dp/dp_display.c | 108 ++++++++++++++++++++++++------------
 drivers/gpu/drm/msm/dp/dp_display.h |   1 -
 2 files changed, 74 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 4f6da636f7c6..44503789d454 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -265,9 +265,9 @@ static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 *dpcd
 	return lttpr_count;
 }
 
-static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp)
+static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp,
+					   struct drm_connector *connector)
 {
-	struct drm_connector *connector = dp->msm_dp_display.connector;
 	const struct drm_display_info *info = &connector->display_info;
 	int rc = 0;
 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
@@ -403,7 +403,8 @@ static int msm_dp_display_handle_irq_hpd(struct msm_dp_display_private *dp)
 	return 0;
 }
 
-static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
+static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp,
+				  struct drm_connector *connector)
 {
 	int ret;
 	struct platform_device *pdev = dp->msm_dp_display.pdev;
@@ -424,7 +425,7 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
 
 	msm_dp_display_host_phy_init(dp);
 
-	ret = msm_dp_display_process_hpd_high(dp);
+	ret = msm_dp_display_process_hpd_high(dp, connector);
 
 	drm_dbg_dp(dp->drm_dev, "After, type=%d sink_count=%d\n",
 			dp->msm_dp_display.connector_type,
@@ -436,7 +437,7 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
 };
 
 static void msm_dp_display_handle_plugged_change(struct msm_dp *msm_dp_display,
-		bool plugged)
+		struct drm_connector *connector, bool plugged)
 {
 	struct msm_dp_display_private *dp;
 
@@ -445,11 +446,11 @@ static void msm_dp_display_handle_plugged_change(struct msm_dp *msm_dp_display,
 
 	/* notify audio subsystem only if sink supports audio */
 	if (dp->audio_supported)
-		drm_connector_hdmi_audio_plugged_notify(msm_dp_display->connector,
-							plugged);
+		drm_connector_hdmi_audio_plugged_notify(connector, plugged);
 }
 
-static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
+static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp,
+				    struct drm_connector *connector)
 {
 	struct platform_device *pdev = dp->msm_dp_display.pdev;
 
@@ -467,7 +468,7 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
 
 	/* Don't forget modes for eDP */
 	if (!dp->msm_dp_display.is_edp)
-		drm_edid_connector_update(dp->msm_dp_display.connector, NULL);
+		drm_edid_connector_update(connector, NULL);
 
 	/* triggered by irq_hdp with sink_count = 0 */
 	if (dp->link->sink_count == 0)
@@ -477,14 +478,14 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
 	 * We don't need separate work for disconnect as
 	 * connect/attention interrupts are disabled
 	 */
-	if (dp->msm_dp_display.connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)
-		drm_dp_set_subconnector_property(dp->msm_dp_display.connector,
+	if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)
+		drm_dp_set_subconnector_property(connector,
 						 connector_status_disconnected,
 						 dp->panel->dpcd,
 						 dp->panel->downstream_ports);
 
 	/* signal the disconnect event early to ensure proper teardown */
-	msm_dp_display_handle_plugged_change(&dp->msm_dp_display, false);
+	msm_dp_display_handle_plugged_change(&dp->msm_dp_display, connector, false);
 
 	drm_dbg_dp(dp->drm_dev, "After, type=%d, sink_count=%d\n",
 			dp->msm_dp_display.connector_type,
@@ -498,7 +499,8 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
 	return 0;
 }
 
-static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp)
+static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp,
+				 struct drm_connector *connector)
 {
 	u32 sink_request;
 	int rc = 0;
@@ -514,7 +516,7 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp)
 		sink_request = dp->link->sink_request;
 		drm_dbg_dp(dp->drm_dev, "sink_request=%d\n", sink_request);
 		if (sink_request & DS_PORT_STATUS_CHANGED)
-			rc = msm_dp_display_process_hpd_high(dp);
+			rc = msm_dp_display_process_hpd_high(dp, connector);
 		else
 			rc = msm_dp_display_handle_irq_hpd(dp);
 	}
@@ -648,7 +650,8 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp, bool force_l
 	return rc;
 }
 
-static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display)
+static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display,
+				      struct drm_connector *connector)
 {
 	struct msm_dp_display_private *dp;
 	u32 rate;
@@ -663,7 +666,7 @@ static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display)
 	}
 
 	/* signal the connect event late to synchronize video and display */
-	msm_dp_display_handle_plugged_change(msm_dp_display, true);
+	msm_dp_display_handle_plugged_change(msm_dp_display, connector, true);
 
 	if (msm_dp_display->psr_supported)
 		msm_dp_ctrl_config_psr(dp->ctrl);
@@ -671,7 +674,8 @@ static int msm_dp_display_post_enable(struct msm_dp *msm_dp_display)
 	return 0;
 }
 
-static int msm_dp_display_disable(struct msm_dp_display_private *dp)
+static int msm_dp_display_disable(struct msm_dp_display_private *dp,
+				  struct drm_connector *connector)
 {
 	struct msm_dp *msm_dp_display = &dp->msm_dp_display;
 
@@ -681,7 +685,7 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp)
 	/* wait only if audio was enabled */
 	if (msm_dp_display->audio_enabled) {
 		/* signal the disconnect event */
-		msm_dp_display_handle_plugged_change(msm_dp_display, false);
+		msm_dp_display_handle_plugged_change(msm_dp_display, connector, false);
 		if (!wait_for_completion_timeout(&dp->audio_comp,
 				HZ * 5))
 			DRM_ERROR("audio comp timeout\n");
@@ -1314,7 +1318,15 @@ void __exit msm_dp_unregister(void)
 static bool msm_dp_needs_periph_flush(const struct msm_dp *msm_dp_display,
 				      const struct drm_display_mode *mode)
 {
-	return drm_mode_is_420_only(&msm_dp_display->connector->display_info, mode);
+	struct msm_dp_display_private *dp = container_of(msm_dp_display,
+			struct msm_dp_display_private, msm_dp_display);
+
+	/*
+	 * The YUV-420 output format is determined during ->mode_set(), which
+	 * has already run by the time this is queried at flush time; use the
+	 * cached value so no connector lookup is needed here.
+	 */
+	return dp->panel->msm_dp_mode.out_fmt_is_yuv_420;
 }
 
 bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display)
@@ -1329,6 +1341,25 @@ bool msm_dp_wide_bus_available(const struct msm_dp *msm_dp_display)
 	return dp->wide_bus_supported;
 }
 
+static struct drm_connector *
+msm_dp_display_get_connector(struct msm_dp *msm_dp_display)
+{
+	struct drm_encoder *encoder = msm_dp_display->bridge->encoder;
+	struct drm_connector_list_iter conn_iter;
+	struct drm_connector *connector, *found = NULL;
+
+	drm_connector_list_iter_begin(msm_dp_display->drm_dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter) {
+		if (drm_connector_has_possible_encoder(connector, encoder)) {
+			found = connector;
+			break;
+		}
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	return found;
+}
+
 void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *root, bool is_edp)
 {
 	struct msm_dp_display_private *dp;
@@ -1338,7 +1369,9 @@ void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *r
 	dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
 	dev = &dp->msm_dp_display.pdev->dev;
 
-	rc = msm_dp_debug_init(dev, dp->panel, dp->link, dp->msm_dp_display.connector, root, is_edp);
+	rc = msm_dp_debug_init(dev, dp->panel, dp->link,
+			       msm_dp_display_get_connector(msm_dp_display),
+			       root, is_edp);
 	if (rc)
 		DRM_ERROR("failed to initialize debug, rc = %d\n", rc);
 }
@@ -1347,6 +1380,7 @@ static int msm_dp_modeset_init(struct msm_display *display,
 			       struct drm_device *dev, struct drm_encoder *encoder)
 {
 	struct msm_dp *msm_dp_display = container_of(display, struct msm_dp, display);
+	struct drm_connector *connector;
 	int ret;
 
 	msm_dp_display->drm_dev = dev;
@@ -1358,12 +1392,11 @@ static int msm_dp_modeset_init(struct msm_display *display,
 		return ret;
 	}
 
-	msm_dp_display->connector = msm_dp_drm_connector_init(msm_dp_display, encoder);
-	if (IS_ERR(msm_dp_display->connector)) {
-		ret = PTR_ERR(msm_dp_display->connector);
+	connector = msm_dp_drm_connector_init(msm_dp_display, encoder);
+	if (IS_ERR(connector)) {
+		ret = PTR_ERR(connector);
 		DRM_DEV_ERROR(dev->dev,
 			"failed to create dp connector: %d\n", ret);
-		msm_dp_display->connector = NULL;
 		return ret;
 	}
 
@@ -1454,14 +1487,17 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
 {
 	struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
 	struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
+	struct drm_connector *connector;
 	int rc = 0;
 	struct msm_dp_display_private *msm_dp_display;
 	bool force_link_train = false;
 
 	msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
 
+	connector = drm_atomic_get_new_connector_for_encoder(state, drm_bridge->encoder);
+
 	if (dp->is_edp)
-		msm_dp_hpd_plug_handle(msm_dp_display);
+		msm_dp_hpd_plug_handle(msm_dp_display, connector);
 
 	if (pm_runtime_resume_and_get(&dp->pdev->dev)) {
 		DRM_ERROR("failed to pm_runtime_resume\n");
@@ -1485,10 +1521,10 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
 
 	msm_dp_display_enable(msm_dp_display, force_link_train);
 
-	rc = msm_dp_display_post_enable(dp);
+	rc = msm_dp_display_post_enable(dp, connector);
 	if (rc) {
 		DRM_ERROR("DP display post enable failed, rc=%d\n", rc);
-		msm_dp_display_disable(msm_dp_display);
+		msm_dp_display_disable(msm_dp_display, connector);
 	}
 
 	drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type);
@@ -1512,13 +1548,17 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
 	struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
 	struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
 	struct msm_dp_display_private *msm_dp_display;
+	struct drm_connector *connector;
 
 	msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
 
+	connector = drm_atomic_get_old_connector_for_encoder(state,
+							     drm_bridge->encoder);
+
 	if (dp->is_edp)
-		msm_dp_hpd_unplug_handle(msm_dp_display);
+		msm_dp_hpd_unplug_handle(msm_dp_display, connector);
 
-	msm_dp_display_disable(msm_dp_display);
+	msm_dp_display_disable(msm_dp_display, connector);
 
 	drm_dbg_dp(dp->drm_dev, "type=%d Done\n", dp->connector_type);
 
@@ -1581,15 +1621,15 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge,
 
 	if (status == connector_status_connected) {
 		if (hpd_link_status == ISR_HPD_REPLUG_COUNT) {
-			msm_dp_hpd_unplug_handle(dp);
-			msm_dp_hpd_plug_handle(dp);
+			msm_dp_hpd_unplug_handle(dp, connector);
+			msm_dp_hpd_plug_handle(dp, connector);
 		} else if (hpd_link_status == ISR_IRQ_HPD_PULSE_COUNT) {
-			msm_dp_irq_hpd_handle(dp);
+			msm_dp_irq_hpd_handle(dp, connector);
 		} else {
-			msm_dp_hpd_plug_handle(dp);
+			msm_dp_hpd_plug_handle(dp, connector);
 		}
 	} else {
-		msm_dp_hpd_unplug_handle(dp);
+		msm_dp_hpd_unplug_handle(dp, connector);
 	}
 
 	pm_runtime_put_sync(&msm_dp_display->pdev->dev);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index f1523dbe33d5..a93904ea33c7 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -16,7 +16,6 @@ struct msm_dp {
 
 	struct drm_device *drm_dev;
 	struct platform_device *pdev;
-	struct drm_connector *connector;
 	struct drm_bridge *next_bridge;
 	struct drm_bridge *bridge;
 	bool audio_enabled;

-- 
2.47.3


  parent reply	other threads:[~2026-07-22  6:37 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-22  6:36 [PATCH 00/24] drm/msm: introduce the struct msm_display interface Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 01/24] drm/msm/dp: reject YUV420-only modes without VSC SDP support Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 02/24] drm/msm/dp: drop the always-true yuv_supported argument Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 03/24] drm/msm: create the display connectors from common code Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 04/24] drm/msm: introduce the struct msm_display interface Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 05/24] drm/msm: route the display snapshot through the " Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 06/24] drm/msm/hdmi: capture the HDMI registers in the display snapshot Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 07/24] drm/msm: add the wide_bus_enabled callback to msm_display Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 08/24] drm/msm: add the needs_periph_flush " Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 09/24] drm/msm: add the is_cmd_mode " Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 10/24] drm/msm: add the get_dsc_config " Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 11/24] drm/msm: add the get_te_source " Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 12/24] drm/msm: add is_bonded and needs_encoder callbacks " Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 13/24] drm/msm/hdmi: use dev_get_drvdata() in msm_hdmi_unbind() Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 14/24] drm/msm: store the display sub-blocks as struct msm_display Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 15/24] drm/msm/dp: do not reject wide-bus modes while a YUV420 mode is active Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 16/24] drm/msm/dp: remove cached drm_edid from panel Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 17/24] drm/msm/dp: drop deprecated .mode_set() and use .atomic_pre_enable Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 18/24] drm/msm/hdmi: cache is_hdmi instead of storing the connector Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 19/24] drm/msm/dp: drop redundant panel->connector Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 20/24] drm/msm/dp: use drm_display_info in mode_valid callbacks Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 21/24] drm/msm/dp: guard subconnector setup on the connector type Dmitry Baryshkov
2026-07-22  6:36 ` Dmitry Baryshkov [this message]
2026-07-22  6:36 ` [PATCH 23/24] drm/msm: create the bridge connectors from common code Dmitry Baryshkov
2026-07-22  6:36 ` [PATCH 24/24] drm/bridge-connector: attach the DP subconnector property Dmitry Baryshkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260722-drm-msm-display-interface-v1-22-368c10fe62fd@oss.qualcomm.com \
    --to=dmitry.baryshkov@oss.qualcomm.com \
    --cc=Laurent.pinchart@ideasonboard.com \
    --cc=abhinav.kumar@linux.dev \
    --cc=airlied@gmail.com \
    --cc=andrzej.hajda@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=freedreno@lists.freedesktop.org \
    --cc=jernej.skrabec@gmail.com \
    --cc=jesszhan0024@gmail.com \
    --cc=jonas@kwiboo.se \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luca.ceresoli@bootlin.com \
    --cc=lumag@kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=marijn.suijten@somainline.org \
    --cc=mripard@kernel.org \
    --cc=neil.armstrong@linaro.org \
    --cc=rfoss@kernel.org \
    --cc=robin.clark@oss.qualcomm.com \
    --cc=sean@poorly.run \
    --cc=simona@ffwll.ch \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®