drm/msm/dp: Rely on hpd_enable/disable callbacks
authorBjorn Andersson <bjorn.andersson@linaro.org>
Wed, 7 Dec 2022 22:00:08 +0000 (14:00 -0800)
committerDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Mon, 9 Jan 2023 01:06:43 +0000 (03:06 +0200)
The DisplayPort controller's internal HPD interrupt handling is used for
cases where the HPD signal is connected to a GPIO which is pinmuxed into
the DisplayPort controller. In other configurations the HPD notification
might be delivered by the DRM framework from an associated bridge.

This difference is not appropriately represented by the "is_edp"
boolean, but is properly represented by the frameworks invocation of the
hpd_enable() and hpd_disable() callbacks. Switch the current condition
to rely on these callbacks instead.

This ensures appropriate handling of the three cases; no bridge
connected, a bridge without DRM_BRIDGE_OP_HPD and a bridge with
DRM_BRIDGE_OP_HPD.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/514414/
Link: https://lore.kernel.org/r/20221207220012.16529-9-quic_bjorande@quicinc.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
drivers/gpu/drm/msm/dp/dp_display.c
drivers/gpu/drm/msm/dp/dp_display.h
drivers/gpu/drm/msm/dp/dp_drm.c
drivers/gpu/drm/msm/dp/dp_drm.h

index 61bca368e7a91ced6f75c394235153077569e57f..720dc2c812d68ac5622fb49db6f50275d56e6d8a 100644 (file)
@@ -610,8 +610,10 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
        }
 
        /* enable HDP irq_hpd/replug interrupt */
-       dp_catalog_hpd_config_intr(dp->catalog,
-               DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true);
+       if (dp->dp_display.internal_hpd)
+               dp_catalog_hpd_config_intr(dp->catalog,
+                                          DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK,
+                                          true);
 
        drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n",
                        dp->dp_display.connector_type, state);
@@ -651,8 +653,10 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
                        dp->dp_display.connector_type, state);
 
        /* disable irq_hpd/replug interrupts */
-       dp_catalog_hpd_config_intr(dp->catalog,
-               DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, false);
+       if (dp->dp_display.internal_hpd)
+               dp_catalog_hpd_config_intr(dp->catalog,
+                                          DP_DP_IRQ_HPD_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK,
+                                          false);
 
        /* unplugged, no more irq_hpd handle */
        dp_del_event(dp, EV_IRQ_HPD_INT);
@@ -678,7 +682,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
        }
 
        /* disable HPD plug interrupts */
-       dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, false);
+       if (dp->dp_display.internal_hpd)
+               dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, false);
 
        /*
         * We don't need separate work for disconnect as
@@ -696,7 +701,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
        dp_display_handle_plugged_change(&dp->dp_display, false);
 
        /* enable HDP plug interrupt to prepare for next plugin */
-       if (!dp->dp_display.is_edp)
+       if (dp->dp_display.internal_hpd)
                dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true);
 
        drm_dbg_dp(dp->drm_dev, "After, type=%d hpd_state=%d\n",
@@ -1081,8 +1086,8 @@ static void dp_display_config_hpd(struct dp_display_private *dp)
        dp_display_host_init(dp);
        dp_catalog_ctrl_hpd_config(dp->catalog);
 
-       /* Enable plug and unplug interrupts only for external DisplayPort */
-       if (!dp->dp_display.is_edp)
+       /* Enable plug and unplug interrupts only if requested */
+       if (dp->dp_display.internal_hpd)
                dp_catalog_hpd_config_intr(dp->catalog,
                                DP_DP_HPD_PLUG_INT_MASK |
                                DP_DP_HPD_UNPLUG_INT_MASK,
@@ -1374,8 +1379,7 @@ static int dp_pm_resume(struct device *dev)
 
        dp_catalog_ctrl_hpd_config(dp->catalog);
 
-
-       if (!dp->dp_display.is_edp)
+       if (dp->dp_display.internal_hpd)
                dp_catalog_hpd_config_intr(dp->catalog,
                                DP_DP_HPD_PLUG_INT_MASK |
                                DP_DP_HPD_UNPLUG_INT_MASK,
@@ -1772,3 +1776,19 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
        dp_display->dp_mode.h_active_low =
                !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
 }
+
+void dp_bridge_hpd_enable(struct drm_bridge *bridge)
+{
+       struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge);
+       struct msm_dp *dp_display = dp_bridge->dp_display;
+
+       dp_display->internal_hpd = true;
+}
+
+void dp_bridge_hpd_disable(struct drm_bridge *bridge)
+{
+       struct msm_dp_bridge *dp_bridge = to_dp_bridge(bridge);
+       struct msm_dp *dp_display = dp_bridge->dp_display;
+
+       dp_display->internal_hpd = false;
+}
index dcedf021f7fe1ad8449e175c1566c4a5c50993b2..371337d0fae26606bf46c2538ec196174360050e 100644 (file)
@@ -21,6 +21,7 @@ struct msm_dp {
        bool power_on;
        unsigned int connector_type;
        bool is_edp;
+       bool internal_hpd;
 
        hdmi_codec_plugged_cb plugged_cb;
 
index 6db82f9b03afb7d79272d85b10f77b1f47080d81..9d03b6ee3c41b2dcc3dd8d619e894409a96b5ec1 100644 (file)
@@ -102,6 +102,8 @@ static const struct drm_bridge_funcs dp_bridge_ops = {
        .get_modes    = dp_bridge_get_modes,
        .detect       = dp_bridge_detect,
        .atomic_check = dp_bridge_atomic_check,
+       .hpd_enable   = dp_bridge_hpd_enable,
+       .hpd_disable  = dp_bridge_hpd_disable,
 };
 
 struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
index 82035dbb05789122ce83cac44ca572e5fb5b01e2..1f871b5550066bf9cb48e8d07079ee03902457fb 100644 (file)
@@ -32,5 +32,7 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
 void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
                        const struct drm_display_mode *mode,
                        const struct drm_display_mode *adjusted_mode);
+void dp_bridge_hpd_enable(struct drm_bridge *bridge);
+void dp_bridge_hpd_disable(struct drm_bridge *bridge);
 
 #endif /* _DP_DRM_H_ */