The source device should ensure the sink is ready before proceeding to read the sink capability or performing any aux transactions. The sink will indicate its readiness by asserting the HPD line.
The eDP sink requires power from the source and its HPD line will be asserted only after the panel is powered on. The panel power will be enabled from the panel-edp driver. The controller driver needs to wait for the hpd line to be asserted by the sink. Signed-off-by: Sankeerth Billakanti <quic_sbill...@quicinc.com> --- drivers/gpu/drm/msm/dp/dp_aux.c | 6 ++++++ drivers/gpu/drm/msm/dp/dp_catalog.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 1 + drivers/gpu/drm/msm/dp/dp_reg.h | 7 ++++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index 6d36f63..2ddc303 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -337,6 +337,12 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, goto exit; } + ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog); + if (ret) { + DRM_DEBUG_DP("DP sink not ready for aux transactions\n"); + goto exit; + } + dp_aux_update_offset_and_segment(aux, msg); dp_aux_transfer_helper(aux, msg, true); diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index fac815f..2c3b0f7 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -242,6 +242,29 @@ void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog) phy_calibrate(phy); } +int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog) +{ + u32 state, hpd_en, timeout; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + hpd_en = dp_read_aux(catalog, REG_DP_DP_HPD_CTRL) & + DP_DP_HPD_CTRL_HPD_EN; + + /* no-hpd case */ + if (!hpd_en) + return 0; + + /* Poll for HPD connected status */ + timeout = dp_read_aux(catalog, REG_DP_DP_HPD_EVENT_TIME_0) & + DP_HPD_CONNECT_TIME_MASK; + + return readl_poll_timeout(catalog->io->dp_controller.aux.base + + REG_DP_DP_HPD_INT_STATUS, + state, state & DP_DP_HPD_STATE_STATUS_CONNECTED, + 2000, timeout); +} + static void dump_regs(void __iomem *base, int len) { int i; diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 7dea101..45140a3 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -84,6 +84,7 @@ int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog); void dp_catalog_aux_reset(struct dp_catalog *dp_catalog); void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable); void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog); +int dp_catalog_aux_wait_for_hpd_connect_state(struct dp_catalog *dp_catalog); u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog); /* DP Controller APIs */ diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 2686028..d68c71b 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -53,9 +53,14 @@ #define DP_DP_HPD_REFTIMER_ENABLE (1 << 16) #define REG_DP_DP_HPD_EVENT_TIME_0 (0x0000001C) -#define REG_DP_DP_HPD_EVENT_TIME_1 (0x00000020) #define DP_DP_HPD_EVENT_TIME_0_VAL (0x3E800FA) +#define DP_HPD_GLITCH_TIME_MASK (0xFFFC0000) +#define DP_HPD_CONNECT_TIME_MASK (0x0003FFFF) + +#define REG_DP_DP_HPD_EVENT_TIME_1 (0x00000020) #define DP_DP_HPD_EVENT_TIME_1_VAL (0x1F407D0) +#define DP_HPD_DISCONNECT_TIME_MASK (0xFFFFC000) +#define DP_IRQ_HPD_MAX_TIME_MASK (0x00003FFF) #define REG_DP_AUX_CTRL (0x00000030) #define DP_AUX_CTRL_ENABLE (0x00000001) -- 2.7.4