|
@@ -2396,6 +2396,71 @@ static void sde_kms_destroy(struct msm_kms *kms)
|
|
kfree(sde_kms);
|
|
kfree(sde_kms);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void sde_kms_helper_clear_dim_layers(struct drm_atomic_state *state, struct drm_crtc *crtc)
|
|
|
|
+{
|
|
|
|
+ struct drm_crtc_state *crtc_state = NULL;
|
|
|
|
+ struct sde_crtc_state *c_state;
|
|
|
|
+
|
|
|
|
+ if (!state || !crtc) {
|
|
|
|
+ SDE_ERROR("invalid params\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
|
|
|
|
+ c_state = to_sde_crtc_state(crtc_state);
|
|
|
|
+
|
|
|
|
+ _sde_crtc_clear_dim_layers_v1(crtc_state);
|
|
|
|
+ set_bit(SDE_CRTC_DIRTY_DIM_LAYERS, c_state->dirty);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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 || !enc->crtc) {
|
|
|
|
+ SDE_ERROR("invalid params for enc:%d\n", DRMID(enc));
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ crtc_state = drm_atomic_get_crtc_state(state, enc->crtc);
|
|
|
|
+ if (IS_ERR(crtc_state)) {
|
|
|
|
+ ret = PTR_ERR(crtc_state);
|
|
|
|
+ SDE_ERROR("error %d getting crtc %d state\n",
|
|
|
|
+ ret, DRMID(enc->crtc));
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static void _sde_kms_plane_force_remove(struct drm_plane *plane,
|
|
static void _sde_kms_plane_force_remove(struct drm_plane *plane,
|
|
struct drm_atomic_state *state)
|
|
struct drm_atomic_state *state)
|
|
{
|
|
{
|
|
@@ -2429,8 +2494,9 @@ static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file,
|
|
struct drm_framebuffer *fb, *tfb;
|
|
struct drm_framebuffer *fb, *tfb;
|
|
struct list_head fbs;
|
|
struct list_head fbs;
|
|
struct drm_plane *plane;
|
|
struct drm_plane *plane;
|
|
|
|
+ struct drm_crtc *crtc = NULL;
|
|
|
|
+ unsigned int crtc_mask = 0;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
- u32 plane_mask = 0;
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&fbs);
|
|
INIT_LIST_HEAD(&fbs);
|
|
|
|
|
|
@@ -2439,11 +2505,10 @@ static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file,
|
|
list_move_tail(&fb->filp_head, &fbs);
|
|
list_move_tail(&fb->filp_head, &fbs);
|
|
|
|
|
|
drm_for_each_plane(plane, dev) {
|
|
drm_for_each_plane(plane, dev) {
|
|
- if (plane->fb == fb) {
|
|
|
|
- plane_mask |=
|
|
|
|
- 1 << drm_plane_index(plane);
|
|
|
|
- _sde_kms_plane_force_remove(
|
|
|
|
- plane, state);
|
|
|
|
|
|
+ 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
@@ -2454,13 +2519,28 @@ static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file,
|
|
|
|
|
|
if (list_empty(&fbs)) {
|
|
if (list_empty(&fbs)) {
|
|
SDE_DEBUG("skip commit as no fb(s)\n");
|
|
SDE_DEBUG("skip commit as no fb(s)\n");
|
|
- drm_atomic_state_put(state);
|
|
|
|
return 0;
|
|
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);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ sde_kms_helper_clear_dim_layers(state, crtc);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SDE_EVT32(state, crtc_mask);
|
|
|
|
+ SDE_DEBUG("null commit after removing all the pipes\n");
|
|
ret = drm_atomic_commit(state);
|
|
ret = drm_atomic_commit(state);
|
|
|
|
|
|
|
|
+error:
|
|
if (ret) {
|
|
if (ret) {
|
|
/*
|
|
/*
|
|
* move the fbs back to original list, so it would be
|
|
* move the fbs back to original list, so it would be
|
|
@@ -3584,12 +3664,7 @@ static void _sde_kms_null_commit(struct drm_device *dev,
|
|
struct drm_encoder *enc)
|
|
struct drm_encoder *enc)
|
|
{
|
|
{
|
|
struct drm_modeset_acquire_ctx ctx;
|
|
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_atomic_state *state = NULL;
|
|
- struct drm_crtc_state *crtc_state = NULL;
|
|
|
|
- struct drm_connector_state *conn_state = NULL;
|
|
|
|
int retry_cnt = 0;
|
|
int retry_cnt = 0;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
@@ -3613,32 +3688,10 @@ retry:
|
|
}
|
|
}
|
|
|
|
|
|
state->acquire_ctx = &ctx;
|
|
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)
|
|
if (ret)
|
|
- SDE_ERROR("error %d setting the crtc\n", ret);
|
|
|
|
|
|
+ goto end;
|
|
|
|
|
|
ret = drm_atomic_commit(state);
|
|
ret = drm_atomic_commit(state);
|
|
if (ret)
|
|
if (ret)
|