msm_dp_display_prepare_link(), msm_dp_display_disable(), and
msm_dp_hpd_unplug_handle() all treat dp->link->sink_count == 0 as
"nothing is connected", and in msm_dp_display_prepare_link() this
causes probe/enable to fail outright with -ENOTCONN.

This is correct for external DisplayPort, where a compliant sink is
required to report a valid DP_SINK_COUNT over the AUX channel. It is
not correct for eDP: some eDP sinks -- particularly fixed-format
eDP-to-HDMI bridge chips with no downstream AUX-capable panel
behind them -- never populate DP_SINK_COUNT with a nonzero value,
even while otherwise participating normally in DPCD capability
exchange and link training.

drm_dp_read_sink_count_cap() already accounts for this by excluding
eDP connectors from the sink-count requirement for other DPCD-derived
checks (msm_dp_bridge_detect() takes care). Apply the same exemption
to the raw sink_count reads in this file via a small shared
helper, so eDP outputs with a non-AUX-capable downstream sink are
not treated as permanently disconnected.

Tested on a Qualcomm QCS6490-based board driving a fixed-format
eDP-to-HDMI bridge IC (chrontel,ch7218a) with no negotiable
DPCD-capable panel behind it; without this fix,
msm_dp_display_prepare_link() unconditionally returns -ENOTCONN
and the display never comes up.

Fixes: ca16db3d18cf ("drm/msm/dp: break up dp_display_enable into two parts")

Signed-off-by: Vivek Kumar <[email protected]>
---
 drivers/gpu/drm/msm/dp/dp_display.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index bc646d172abe..9254f080f0ea 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -400,6 +400,12 @@ static int msm_dp_display_handle_irq_hpd(struct 
msm_dp_display_private *dp)
        return 0;
 }
 
+static inline bool msm_dp_link_no_sink(struct msm_dp_display_private *dp)
+{
+       /* eDP sinks are not required to report a valid sink count */
+       return !dp->msm_dp_display.is_edp && dp->link->sink_count == 0;
+}
+
 static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
 {
        int ret;
@@ -467,7 +473,7 @@ static int msm_dp_hpd_unplug_handle(struct 
msm_dp_display_private *dp)
                drm_edid_connector_update(dp->msm_dp_display.connector, NULL);
 
        /* triggered by irq_hdp with sink_count = 0 */
-       if (dp->link->sink_count == 0)
+       if (msm_dp_link_no_sink(dp))
                msm_dp_display_host_phy_exit(dp);
 
        /*
@@ -634,7 +640,7 @@ static int msm_dp_display_prepare_link(struct 
msm_dp_display_private *dp)
                return rc;
        }
 
-       if (dp->link->sink_count == 0)
+       if (msm_dp_link_no_sink(dp))
                return -ENOTCONN;
 
        if (!msm_dp_display->power_on) {
@@ -723,12 +729,12 @@ static int msm_dp_display_disable(struct 
msm_dp_display_private *dp,
        msm_dp_ctrl_off_pixel_clk(dp->ctrl);
 
        /* dongle is still connected but sinks are disconnected */
-       if (dp->link->sink_count == 0)
+       if (msm_dp_link_no_sink(dp))
                msm_dp_link_psm_config(dp->link, &msm_dp_panel->link_info, 
true);
 
        msm_dp_ctrl_off_link(dp->ctrl, msm_dp_panel);
 
-       if (dp->link->sink_count == 0)
+       if (msm_dp_link_no_sink(dp))
                /* re-init the PHY so that we can listen to Dongle disconnect */
                msm_dp_ctrl_reinit_phy(dp->ctrl);
        else
-- 
2.55.0

Reply via email to