Implement the .hpd_enable() and .hpd_disable() bridge callbacks and
extend dw_hdmi_qp_phy_ops with corresponding hooks.

This enables the DRM core to control when HPD interrupts are armed,
which is needed to prevent premature interrupt delivery before the
connector is fully initialized, and to properly quiesce HPD during
suspend.

Tested-by: Maud Spierings <[email protected]>
Tested-by: Diederik de Haas <[email protected]>  # NanoPC-T6 LTS, Rock 5B
Tested-by: Robin Räber <[email protected]>
Tested-by: Igor Paunovic <[email protected]> # RK3588 Orange Pi 5 Plus, 
dual HDMI
Signed-off-by: Cristian Ciocaltea <[email protected]>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 18 ++++++++++++++++++
 include/drm/bridge/dw_hdmi_qp.h              |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c 
b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
index 9abcea92b720..bed743ce3909 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
@@ -974,6 +974,22 @@ static int dw_hdmi_qp_cec_transmit(struct drm_bridge 
*bridge, u8 attempts,
 #define dw_hdmi_qp_cec_transmit NULL
 #endif /* CONFIG_DRM_DW_HDMI_QP_CEC */
 
+static void dw_hdmi_qp_bridge_hpd_enable(struct drm_bridge *bridge)
+{
+       struct dw_hdmi_qp *hdmi = bridge->driver_private;
+
+       if (hdmi->phy.ops->enable_hpd)
+               hdmi->phy.ops->enable_hpd(hdmi, hdmi->phy.data);
+}
+
+static void dw_hdmi_qp_bridge_hpd_disable(struct drm_bridge *bridge)
+{
+       struct dw_hdmi_qp *hdmi = bridge->driver_private;
+
+       if (hdmi->phy.ops->disable_hpd)
+               hdmi->phy.ops->disable_hpd(hdmi, hdmi->phy.data);
+}
+
 static const struct drm_bridge_funcs dw_hdmi_qp_bridge_funcs = {
        .atomic_get_output_bus_fmts = 
drm_atomic_helper_bridge_get_hdmi_output_bus_fmts,
        .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
@@ -982,6 +998,8 @@ static const struct drm_bridge_funcs 
dw_hdmi_qp_bridge_funcs = {
        .atomic_enable = dw_hdmi_qp_bridge_atomic_enable,
        .atomic_disable = dw_hdmi_qp_bridge_atomic_disable,
        .detect = dw_hdmi_qp_bridge_detect,
+       .hpd_enable = dw_hdmi_qp_bridge_hpd_enable,
+       .hpd_disable = dw_hdmi_qp_bridge_hpd_disable,
        .edid_read = dw_hdmi_qp_bridge_edid_read,
        .hdmi_tmds_char_rate_valid = dw_hdmi_qp_bridge_tmds_char_rate_valid,
        .hdmi_clear_avi_infoframe = dw_hdmi_qp_bridge_clear_avi_infoframe,
diff --git a/include/drm/bridge/dw_hdmi_qp.h b/include/drm/bridge/dw_hdmi_qp.h
index 6ea9c561cfef..b80fceffc315 100644
--- a/include/drm/bridge/dw_hdmi_qp.h
+++ b/include/drm/bridge/dw_hdmi_qp.h
@@ -17,6 +17,8 @@ struct dw_hdmi_qp_phy_ops {
        void (*disable)(struct dw_hdmi_qp *hdmi, void *data);
        enum drm_connector_status (*read_hpd)(struct dw_hdmi_qp *hdmi, void 
*data);
        void (*setup_hpd)(struct dw_hdmi_qp *hdmi, void *data);
+       void (*enable_hpd)(struct dw_hdmi_qp *hdmi, void *data);
+       void (*disable_hpd)(struct dw_hdmi_qp *hdmi, void *data);
 };
 
 struct dw_hdmi_qp_plat_data {

-- 
2.55.0

Reply via email to