diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index adbd5a367395..f98d089ea5b1 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -38,6 +38,7 @@ struct dp_aux_private { bool no_send_stop; bool initted; bool is_edp; + bool enable_xfers; u32 offset; u32 segment; @@ -304,6 +305,17 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, goto exit; } + /* + * If we're using DP and an external display isn't connected then the + * transfer won't succeed. Return right away. If we don't do this we + * can end up with long timeouts if someone tries to access the DP AUX + * character device when no DP device is connected. + */ + if (!aux->is_edp && !aux->enable_xfers) { + ret = -ENXIO; + goto exit; + } + /* * For eDP it's important to give a reasonably long wait here for HPD * to be asserted. This is because the panel driver may have _just_ @@ -436,6 +448,14 @@ irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux) return IRQ_HANDLED; } +void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled) +{ + struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + aux->enable_xfers = enabled; +} + void dp_aux_reconfig(struct drm_dp_aux *dp_aux) { struct dp_aux_private *aux; diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h index f47d591c1f54..4f65e892a807 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.h +++ b/drivers/gpu/drm/msm/dp/dp_aux.h @@ -12,6 +12,7 @@ int dp_aux_register(struct drm_dp_aux *dp_aux); void dp_aux_unregister(struct drm_dp_aux *dp_aux); irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux); +void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled); void dp_aux_init(struct drm_dp_aux *dp_aux); void dp_aux_deinit(struct drm_dp_aux *dp_aux); void dp_aux_reconfig(struct drm_dp_aux *dp_aux); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 3539767feca4..cdb299dd0158 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -550,6 +550,8 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) int ret; struct platform_device *pdev = dp->dp_display.pdev; + dp_aux_enable_xfers(dp->aux, true); + mutex_lock(&dp->event_mutex); state = dp->hpd_state; @@ -615,6 +617,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) u32 state; struct platform_device *pdev = dp->dp_display.pdev; + dp_aux_enable_xfers(dp->aux, false); + mutex_lock(&dp->event_mutex); state = dp->hpd_state;