On 5 December 2022 20:44:30 GMT+03:00, Bjorn Andersson <quic_bjorande@xxxxxxxxxxx> wrote: >From: Bjorn Andersson <bjorn.andersson@xxxxxxxxxx> > >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@xxxxxxxxxx> >Signed-off-by: Bjorn Andersson <quic_bjorande@xxxxxxxxxxx> >--- > >Worth mentioning, I did look into moving the HPD enablement/disablement >completely into these new callbacks, but that affect the entire power >management model of the driver, so I think it's worth to tackle that in >subsequent changes. It seems also reasonable to expect that we by such >modifications could leave the block unclocked until the external HPD >notification arrives... I see... I still suppose this is the way to go in the long term. For now: Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> > >Changes since v3: >- Introduced reliance on hpd_enable/disable callbacks instead of next_bridge > > drivers/gpu/drm/msm/dp/dp_display.c | 35 ++++++++++++++++++++--------- > drivers/gpu/drm/msm/dp/dp_display.h | 1 + > drivers/gpu/drm/msm/dp/dp_drm.c | 2 ++ > drivers/gpu/drm/msm/dp/dp_drm.h | 2 ++ > 4 files changed, 30 insertions(+), 10 deletions(-) > >diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c >index bb92c33beff8..3e464c33ff11 100644 >--- a/drivers/gpu/drm/msm/dp/dp_display.c >+++ b/drivers/gpu/drm/msm/dp/dp_display.c >@@ -610,7 +610,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) > } > > /* enable HDP irq_hpd/replug interrupt */ >- if (!dp->dp_display.is_edp) >+ 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); >@@ -653,7 +653,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) > dp->dp_display.connector_type, state); > > /* disable irq_hpd/replug interrupts */ >- if (!dp->dp_display.is_edp) >+ 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); >@@ -682,7 +682,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) > } > > /* disable HPD plug interrupts */ >- 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, false); > > /* >@@ -701,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", >@@ -1086,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, >@@ -1379,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, >@@ -1778,6 +1777,22 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge, > !!(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; >+} >+ > void dp_bridge_hpd_notify(struct drm_bridge *bridge, > enum drm_connector_status status) > { >@@ -1785,8 +1800,8 @@ void dp_bridge_hpd_notify(struct drm_bridge *bridge, > struct msm_dp *dp_display = dp_bridge->dp_display; > struct dp_display_private *dp = container_of(dp_display, struct dp_display_private, dp_display); > >- /* Without next_bridge interrupts are handled by the DP core directly */ >- if (!dp_display->next_bridge) >+ /* Plug events are generated by the dp_display_irq_handler() */ >+ if (dp_display->internal_hpd) > return; > > if (!dp->core_initialized) { >diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h >index dcedf021f7fe..371337d0fae2 100644 >--- a/drivers/gpu/drm/msm/dp/dp_display.h >+++ b/drivers/gpu/drm/msm/dp/dp_display.h >@@ -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; > >diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c >index 3898366ebd5e..275370f21115 100644 >--- a/drivers/gpu/drm/msm/dp/dp_drm.c >+++ b/drivers/gpu/drm/msm/dp/dp_drm.c >@@ -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, > .hpd_notify = dp_bridge_hpd_notify, > }; > >diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h >index 79e6b2cf2d25..250f7c66201f 100644 >--- a/drivers/gpu/drm/msm/dp/dp_drm.h >+++ b/drivers/gpu/drm/msm/dp/dp_drm.h >@@ -32,6 +32,8 @@ 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); > void dp_bridge_hpd_notify(struct drm_bridge *bridge, > enum drm_connector_status status); > -- With best wishes Dmitry