diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index bea70fb8ee..cab71ff257 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -2579,6 +2579,38 @@ static void _sde_kms_plane_force_remove(struct drm_plane *plane, drm_atomic_set_fb_for_plane(plane_state, NULL); } +static int _sde_kms_connector_add_refcount(struct sde_kms *sde_kms, + struct drm_atomic_state *state) +{ + struct drm_device *dev = sde_kms->dev; + struct drm_connector *conn; + struct drm_connector_state *conn_state; + struct drm_connector_list_iter conn_iter; + struct sde_connector_state *c_state; + int ret = 0; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(conn, &conn_iter) { + /* + * Acquire a connector reference to avoid removing + * connector in drm_release for splash and recovery cases. + */ + conn_state = drm_atomic_get_connector_state(state, conn); + if (IS_ERR(conn_state)) { + ret = PTR_ERR(conn_state); + SDE_ERROR("error %d getting connector %d state\n", + ret, DRMID(conn)); + return ret; + } + c_state = to_sde_connector_state(conn_state); + if (c_state->out_fb) + drm_framebuffer_put(c_state->out_fb); + } + drm_connector_list_iter_end(&conn_iter); + + return ret; +} + static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file, struct drm_atomic_state *state) { @@ -2611,6 +2643,8 @@ static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file, if (list_empty(&fbs)) { SDE_DEBUG("skip commit as no fb(s)\n"); + if (sde_kms->dsi_display_count == sde_kms->splash_data.num_splash_displays) + _sde_kms_connector_add_refcount(sde_kms, state); return 0; }