diff options
Diffstat (limited to 'msm/sde/sde_kms.c')
-rw-r--r-- | msm/sde/sde_kms.c | 151 |
1 files changed, 100 insertions, 51 deletions
diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 29804065..150145ed 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1141,10 +1141,12 @@ static void sde_kms_check_for_ext_vote(struct sde_kms *sde_kms, * cases, allow the target to go through a gdsc toggle after * crtc is disabled. */ - if (!crtc_enabled && phandle->is_ext_vote_en) { + if (!crtc_enabled && (phandle->is_ext_vote_en || + !dev->dev->power.runtime_auto)) { pm_runtime_put_sync(sde_kms->dev->dev); - SDE_EVT32(phandle->is_ext_vote_en); pm_runtime_get_sync(sde_kms->dev->dev); + SDE_EVT32(phandle->is_ext_vote_en, + dev->dev->power.runtime_auto); } mutex_unlock(&phandle->ext_client_lock); @@ -1223,6 +1225,7 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, struct drm_encoder *encoder; struct drm_device *dev; int ret; + bool cwb_disabling; if (!kms || !crtc || !crtc->state) { SDE_ERROR("invalid params\n"); @@ -1248,8 +1251,14 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, SDE_ATRACE_BEGIN("sde_kms_wait_for_commit_done"); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->crtc != crtc) - continue; + cwb_disabling = false; + if (encoder->crtc != crtc) { + cwb_disabling = sde_encoder_is_cwb_disabling(encoder, + crtc); + if (!cwb_disabling) + continue; + } + /* * Wait for post-flush if necessary to delay before * plane_cleanup. For example, wait for vsync in case of video @@ -1264,6 +1273,9 @@ static void sde_kms_wait_for_commit_done(struct msm_kms *kms, } sde_crtc_complete_flip(crtc, NULL); + + if (cwb_disabling) + sde_encoder_virt_reset(encoder); } SDE_ATRACE_END("sde_ksm_wait_for_commit_done"); @@ -1274,7 +1286,7 @@ static void sde_kms_prepare_fence(struct msm_kms *kms, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; - int i, rc; + int i; if (!kms || !old_state || !old_state->dev || !old_state->acquire_ctx) { SDE_ERROR("invalid argument(s)\n"); @@ -1282,15 +1294,6 @@ static void sde_kms_prepare_fence(struct msm_kms *kms, } SDE_ATRACE_BEGIN("sde_kms_prepare_fence"); -retry: - /* attempt to acquire ww mutex for connection */ - rc = drm_modeset_lock(&old_state->dev->mode_config.connection_mutex, - old_state->acquire_ctx); - - if (rc == -EDEADLK) { - drm_modeset_backoff(old_state->acquire_ctx); - goto retry; - } /* old_state actually contains updated crtc pointers */ for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { @@ -1589,6 +1592,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_panel_vfp = dsi_display_get_panel_vfp, .get_default_lms = dsi_display_get_default_lms, .set_idle_hint = dsi_display_set_idle_hint, + .get_qsync_min_fps = dsi_display_get_qsync_min_fps, }; static const struct sde_connector_ops wb_ops = { .post_init = sde_wb_connector_post_init, @@ -2188,6 +2192,48 @@ static void sde_kms_destroy(struct msm_kms *kms) kfree(sde_kms); } +static int sde_kms_set_crtc_for_conn(struct drm_device *dev, + struct drm_encoder *enc, struct drm_atomic_state *state) +{ + struct drm_connector *conn = NULL; + struct drm_connector *tmp_conn = NULL; + struct drm_connector_list_iter conn_iter; + struct drm_crtc_state *crtc_state = NULL; + struct drm_connector_state *conn_state = NULL; + int ret = 0; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(tmp_conn, &conn_iter) { + if (enc == tmp_conn->state->best_encoder) { + conn = tmp_conn; + break; + } + } + drm_connector_list_iter_end(&conn_iter); + + if (!conn) { + SDE_ERROR("error in finding conn for enc:%d\n", DRMID(enc)); + return -EINVAL; + } + + crtc_state = drm_atomic_get_crtc_state(state, enc->crtc); + conn_state = drm_atomic_get_connector_state(state, conn); + if (IS_ERR(conn_state)) { + SDE_ERROR("error %d getting connector %d state\n", + ret, DRMID(conn)); + return -EINVAL; + } + + crtc_state->active = true; + ret = drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); + if (ret) + SDE_ERROR("error %d setting the crtc\n", ret); + + _sde_crtc_clear_dim_layers_v1(crtc_state); + + return 0; +} + static void _sde_kms_plane_force_remove(struct drm_plane *plane, struct drm_atomic_state *state) { @@ -2219,8 +2265,9 @@ static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file, struct drm_framebuffer *fb, *tfb; struct list_head fbs; struct drm_plane *plane; + struct drm_crtc *crtc = NULL; + unsigned int crtc_mask = 0; int ret = 0; - u32 plane_mask = 0; INIT_LIST_HEAD(&fbs); @@ -2229,9 +2276,11 @@ static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file, list_move_tail(&fb->filp_head, &fbs); drm_for_each_plane(plane, dev) { - if (plane->fb == fb) { - plane_mask |= - 1 << drm_plane_index(plane); + if (plane->state && + plane->state->fb == fb) { + if (plane->state->crtc) + crtc_mask |= drm_crtc_mask( + plane->state->crtc); _sde_kms_plane_force_remove( plane, state); } @@ -2244,11 +2293,22 @@ 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"); - drm_atomic_state_put(state); return 0; } - SDE_DEBUG("committing after removing all the pipes\n"); + drm_for_each_crtc(crtc, dev) { + if ((crtc_mask & drm_crtc_mask(crtc)) && crtc->state->active) { + struct drm_encoder *drm_enc; + + drm_for_each_encoder_mask(drm_enc, crtc->dev, + crtc->state->encoder_mask) + ret = sde_kms_set_crtc_for_conn( + dev, drm_enc, state); + } + } + + SDE_EVT32(state, crtc_mask); + SDE_DEBUG("null commit after removing all the pipes\n"); ret = drm_atomic_commit(state); if (ret) { @@ -2828,9 +2888,10 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms) return rc; } -static bool sde_kms_check_for_splash(struct msm_kms *kms) +static bool sde_kms_check_for_splash(struct msm_kms *kms, struct drm_crtc *crtc) { struct sde_kms *sde_kms; + struct drm_encoder *encoder; if (!kms) { SDE_ERROR("invalid kms\n"); @@ -2838,7 +2899,18 @@ static bool sde_kms_check_for_splash(struct msm_kms *kms) } sde_kms = to_sde_kms(kms); - return sde_kms->splash_data.num_splash_displays; + + if (!crtc || !sde_kms->splash_data.num_splash_displays) + return !!sde_kms->splash_data.num_splash_displays; + + drm_for_each_encoder_mask(encoder, crtc->dev, + crtc->state->encoder_mask) { + if (sde_encoder_in_cont_splash(encoder)) + return true; + } + + return false; + } static int sde_kms_get_mixer_count(const struct msm_kms *kms, @@ -2891,12 +2963,7 @@ static void _sde_kms_null_commit(struct drm_device *dev, struct drm_encoder *enc) { struct drm_modeset_acquire_ctx ctx; - struct drm_connector *conn = NULL; - struct drm_connector *tmp_conn = NULL; - struct drm_connector_list_iter conn_iter; struct drm_atomic_state *state = NULL; - struct drm_crtc_state *crtc_state = NULL; - struct drm_connector_state *conn_state = NULL; int retry_cnt = 0; int ret = 0; @@ -2920,32 +2987,10 @@ retry: } state->acquire_ctx = &ctx; - drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(tmp_conn, &conn_iter) { - if (enc == tmp_conn->state->best_encoder) { - conn = tmp_conn; - break; - } - } - drm_connector_list_iter_end(&conn_iter); - - if (!conn) { - SDE_ERROR("error in finding conn for enc:%d\n", DRMID(enc)); - goto end; - } - - crtc_state = drm_atomic_get_crtc_state(state, enc->crtc); - conn_state = drm_atomic_get_connector_state(state, conn); - if (IS_ERR(conn_state)) { - SDE_ERROR("error %d getting connector %d state\n", - ret, DRMID(conn)); - goto end; - } - crtc_state->active = true; - ret = drm_atomic_set_crtc_for_connector(conn_state, enc->crtc); + ret = sde_kms_set_crtc_for_conn(dev, enc, state); if (ret) - SDE_ERROR("error %d setting the crtc\n", ret); + goto end; ret = drm_atomic_commit(state); if (ret) @@ -3473,6 +3518,7 @@ static int sde_kms_pd_enable(struct generic_pm_domain *genpd) static int sde_kms_pd_disable(struct generic_pm_domain *genpd) { struct sde_kms *sde_kms = genpd_to_sde_kms(genpd); + struct msm_drm_private *priv; SDE_DEBUG("\n"); @@ -3480,6 +3526,9 @@ static int sde_kms_pd_disable(struct generic_pm_domain *genpd) SDE_EVT32(genpd->device_count); + priv = sde_kms->dev->dev_private; + sde_kms_check_for_ext_vote(sde_kms, &priv->phandle); + return 0; } |