summaryrefslogtreecommitdiff
path: root/msm/sde/sde_kms.c
diff options
context:
space:
mode:
Diffstat (limited to 'msm/sde/sde_kms.c')
-rw-r--r--msm/sde/sde_kms.c151
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;
}