diff --git a/msm/msm_drv.c b/msm/msm_drv.c index 5eb8363e2198..a522ca30d78b 100644 --- a/msm/msm_drv.c +++ b/msm/msm_drv.c @@ -1042,8 +1042,19 @@ static void msm_lastclose(struct drm_device *dev) * commit then ignore the last close call */ if (kms->funcs && kms->funcs->check_for_splash - && kms->funcs->check_for_splash(kms, NULL)) - return; + && kms->funcs->check_for_splash(kms, NULL)) { + msm_wait_event_timeout(priv->pending_crtcs_event, !priv->pending_crtcs, + LASTCLOSE_TIMEOUT_MS, rc); + if (!rc) + DRM_INFO("wait for crtc mask 0x%x failed, commit anyway...\n", + priv->pending_crtcs); + + rc = kms->funcs->trigger_null_flush(kms); + if (rc) { + DRM_ERROR("null flush commit failure during lastclose\n"); + return; + } + } /* * clean up vblank disable immediately as this is the last close. @@ -1543,8 +1554,15 @@ static int msm_release(struct inode *inode, struct file *filp) * refcount > 1. This operation is not triggered from upstream * drm as msm_driver does not support DRIVER_LEGACY feature. */ - if (drm_is_current_master(file_priv)) + if (drm_is_current_master(file_priv)) { + msm_wait_event_timeout(priv->pending_crtcs_event, !priv->pending_crtcs, + LASTCLOSE_TIMEOUT_MS, ret); + if (!ret) + DRM_INFO("wait for crtc mask 0x%x failed, commit anyway...\n", + priv->pending_crtcs); + msm_preclose(dev, file_priv); + } ret = drm_release(inode, filp); filp->private_data = NULL; diff --git a/msm/msm_kms.h b/msm/msm_kms.h index 058f97cdf53a..7c929e1df6f8 100644 --- a/msm/msm_kms.h +++ b/msm/msm_kms.h @@ -126,6 +126,8 @@ struct msm_kms_funcs { struct drm_atomic_state *state); /* check for continuous splash status */ bool (*check_for_splash)(struct msm_kms *kms, struct drm_crtc *crtc); + /*trigger null flush if stuck in cont splash*/ + int (*trigger_null_flush)(struct msm_kms *kms); /* topology lm information */ int (*get_mixer_count)(const struct msm_kms *kms, const struct drm_display_mode *mode, diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 9f7a815c9227..4c5705ce81b3 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -2462,6 +2462,7 @@ static int sde_kms_set_crtc_for_conn(struct drm_device *dev, } crtc_state->active = true; + crtc_state->enable = true; ret = drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); if (ret) SDE_ERROR("error %d setting the crtc\n", ret); @@ -3644,7 +3645,7 @@ static int sde_kms_get_dsc_count(const struct msm_kms *kms, return 0; } -static void _sde_kms_null_commit(struct drm_device *dev, +static int _sde_kms_null_commit(struct drm_device *dev, struct drm_encoder *enc) { struct drm_modeset_acquire_ctx ctx; @@ -3687,6 +3688,8 @@ end: drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); + + return ret; } @@ -3715,6 +3718,36 @@ void sde_kms_display_early_wakeup(struct drm_device *dev, drm_connector_list_iter_end(&conn_iter); } +static int sde_kms_trigger_null_flush(struct msm_kms *kms) +{ + struct sde_kms *sde_kms; + struct sde_splash_display *splash_display; + int i, rc = 0; + + if (!kms) { + SDE_ERROR("invalid kms\n"); + return -EINVAL; + } + + sde_kms = to_sde_kms(kms); + + if (!sde_kms->splash_data.num_splash_displays || + sde_kms->dsi_display_count == sde_kms->splash_data.num_splash_displays) + return rc; + + for (i = 0; i < MAX_DSI_DISPLAYS; i++) { + splash_display = &sde_kms->splash_data.splash_display[i]; + + if (splash_display->cont_splash_enabled && splash_display->encoder) { + SDE_DEBUG("triggering null commit on enc:%d\n", + DRMID(splash_display->encoder)); + SDE_EVT32(DRMID(splash_display->encoder), SDE_EVTLOG_FUNC_ENTRY); + rc = _sde_kms_null_commit(sde_kms->dev, splash_display->encoder); + } + } + + return rc; +} #ifdef CONFIG_DEEPSLEEP static int _sde_kms_pm_deepsleep_helper(struct sde_kms *sde_kms, bool enter) @@ -4070,6 +4103,7 @@ static const struct msm_kms_funcs kms_funcs = { .get_address_space_device = _sde_kms_get_address_space_device, .postopen = _sde_kms_post_open, .check_for_splash = sde_kms_check_for_splash, + .trigger_null_flush = sde_kms_trigger_null_flush, .get_mixer_count = sde_kms_get_mixer_count, .get_dsc_count = sde_kms_get_dsc_count, };