diff options
author | Jiun Yu <jiun.yu@samsung.com> | 2019-12-08 10:14:52 +0900 |
---|---|---|
committer | Adrian Salido <salidoa@google.com> | 2020-09-29 13:59:17 -0700 |
commit | 826e799777079f1a5f8a7b59eaf6bfc9b72d5a44 (patch) | |
tree | dc78e594e4c86932db5a1481906a4ae70ac4cd38 | |
parent | f232dce7444037f0e9278086afd59852a21d097f (diff) | |
download | display-826e799777079f1a5f8a7b59eaf6bfc9b72d5a44.tar.gz |
drm: samsung: use normalized zpos
The normalized_zpos is used to normalize z-position of the planes.
For example, if 3 planes are used and each zpos is 0, 3 and 5 then
normalized_zpos will be 0, 1 and 2.
If it is used, DECON windows are never conflict.
BUG: 142884233
Signed-off-by: Adrian Salido <salidoa@google.com>
Signed-off-by: Jiun Yu <jiun.yu@samsung.com>
Change-Id: Ib658c2ed096b0349ea544cb458883e9ed6c39142
-rw-r--r-- | samsung/exynos_drm_crtc.c | 3 | ||||
-rw-r--r-- | samsung/exynos_drm_decon.c | 5 | ||||
-rw-r--r-- | samsung/exynos_drm_decon.h | 3 | ||||
-rw-r--r-- | samsung/exynos_drm_fb.c | 2 | ||||
-rw-r--r-- | samsung/exynos_drm_plane.c | 74 |
5 files changed, 37 insertions, 50 deletions
diff --git a/samsung/exynos_drm_crtc.c b/samsung/exynos_drm_crtc.c index 2f11e00..eafa78f 100644 --- a/samsung/exynos_drm_crtc.c +++ b/samsung/exynos_drm_crtc.c @@ -100,12 +100,9 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct decon_device *decon = exynos_crtc->ctx; if (exynos_crtc->ops->atomic_flush) exynos_crtc->ops->atomic_flush(exynos_crtc); - - decon->req_windows = 0; } static enum drm_mode_status exynos_crtc_mode_valid(struct drm_crtc *crtc, diff --git a/samsung/exynos_drm_decon.c b/samsung/exynos_drm_decon.c index 99385bb..fc95602 100644 --- a/samsung/exynos_drm_decon.c +++ b/samsung/exynos_drm_decon.c @@ -210,7 +210,10 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, win_info.plane_alpha = hw_alpha; win_info.blend = state->base.pixel_blend_mode; - zpos = state->base.zpos; + zpos = state->base.normalized_zpos; + if (zpos == 0 && hw_alpha == EXYNOS_PLANE_ALPHA_MAX) + win_info.blend = DRM_MODE_BLEND_PIXEL_NONE; + decon_reg_set_window_control(decon->id, zpos, &win_info, is_colormap); if (!is_colormap) { diff --git a/samsung/exynos_drm_decon.h b/samsung/exynos_drm_decon.h index 8ebe6d0..8a89ee2 100644 --- a/samsung/exynos_drm_decon.h +++ b/samsung/exynos_drm_decon.h @@ -229,9 +229,6 @@ struct decon_device { spinlock_t slock; int decon_cnt; - - /* bitmask of newly requested windows */ - unsigned long req_windows; }; extern struct dpu_bts_ops dpu_bts_control; diff --git a/samsung/exynos_drm_fb.c b/samsung/exynos_drm_fb.c index 838ecc4..272b4aa 100644 --- a/samsung/exynos_drm_fb.c +++ b/samsung/exynos_drm_fb.c @@ -286,7 +286,7 @@ void plane_state_to_win_config(struct decon_device *decon, int zpos; unsigned int simplified_rot; - zpos = state->base.zpos; + zpos = state->base.normalized_zpos; win_config = &decon->bts.win_config[zpos]; win_config->src_x = state->base.src_x >> 16; diff --git a/samsung/exynos_drm_plane.c b/samsung/exynos_drm_plane.c index 13a5413..dec4bb1 100644 --- a/samsung/exynos_drm_plane.c +++ b/samsung/exynos_drm_plane.c @@ -20,7 +20,6 @@ #include <exynos_drm_crtc.h> #include <exynos_drm_fb.h> #include <exynos_drm_plane.h> -#include <exynos_drm_decon.h> #include <exynos_drm_dpp.h> /* @@ -173,6 +172,9 @@ static void exynos_drm_plane_reset(struct drm_plane *plane) plane->state = &exynos_state->base; plane->state->plane = plane; plane->state->zpos = exynos_plane->config->zpos; + plane->state->normalized_zpos = exynos_plane->config->zpos; + plane->state->alpha = DRM_BLEND_ALPHA_OPAQUE; + plane->state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; } } @@ -245,6 +247,9 @@ exynos_drm_plane_check_format(const struct exynos_drm_plane_config *config, { struct drm_framebuffer *fb = state->base.fb; + if (!fb) + return 0; + if (fb->modifier) { if (fb->modifier & DRM_FORMAT_MOD_ARM_AFBC(0)) return 0; @@ -266,7 +271,6 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, struct exynos_drm_plane_state *exynos_state = to_exynos_plane_state(state); struct dpp_device *dpp = plane_to_dpp(exynos_plane); - struct decon_device *decon; struct drm_crtc_state *new_crtc_state; int ret = 0; @@ -275,8 +279,6 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, if (!state->crtc || !state->fb) return 0; - decon = to_exynos_crtc(state->crtc)->ctx; - new_crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); @@ -296,70 +298,58 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, if (ret) return ret; - /* - * If multiple planes request the same zpos which means DECON window - * number, HW resources can be conflicted. - */ - if (test_and_set_bit(exynos_state->base.zpos, &decon->req_windows)) { - DRM_ERROR("zpos %d conflict.\n", exynos_state->base.zpos); - clear_bit(exynos_state->base.zpos, &decon->req_windows); - return -EINVAL; - } - DRM_DEBUG("%s -\n", __func__); return ret; } +static void exynos_plane_disable(struct drm_plane *plane, struct drm_crtc *crtc) +{ + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); + const struct dpp_device *dpp = plane_to_dpp(exynos_plane); + const unsigned int num_planes = hweight32(crtc->state->plane_mask); + + pr_debug("%s: win_id=%d/%d zpos=%d", __func__, + dpp->win_id, num_planes, plane->state->normalized_zpos); + + /* + * By using normalized zpos, any zpos beyond number of planes can be + * disabled safely (i.e. window zpos is not going to be used) + */ + if (exynos_crtc->ops->disable_plane && (dpp->win_id < MAX_PLANE) && + (dpp->win_id >= num_planes)) + exynos_crtc->ops->disable_plane(exynos_crtc, exynos_plane); +} + static void exynos_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { struct drm_plane_state *state = plane->state; - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(state->crtc); + struct exynos_drm_crtc *exynos_crtc; struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); const struct dpp_device *dpp = plane_to_dpp(exynos_plane); - struct decon_device *decon; if (!state->crtc) return; - /* - * If requested zpos(window) and previously connected window(zpos) are - * NOT same for the plane, previous connected window should be disabled. - * - * However, currently requested zpos(window) can NOT disabled. - */ - decon = exynos_crtc->ctx; - if ((dpp->win_id != plane->state->zpos) && (dpp->win_id < MAX_PLANE) && - !test_bit(dpp->win_id, &decon->req_windows)) - exynos_crtc->ops->disable_plane(exynos_crtc, exynos_plane); + exynos_crtc = to_exynos_crtc(state->crtc); + + if (!state->visible || (dpp->win_id != state->normalized_zpos)) + exynos_plane_disable(plane, state->crtc); if (state->visible && exynos_crtc->ops->update_plane) exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane); - else if ((exynos_crtc->ops->disable_plane) && (dpp->win_id < MAX_PLANE)) - exynos_crtc->ops->disable_plane(exynos_crtc, exynos_plane); } static void exynos_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_state *old_state) { - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_crtc *exynos_crtc; - const struct dpp_device *dpp = plane_to_dpp(exynos_plane); - const struct decon_device *decon; - if (!old_state || !old_state->crtc) return; - exynos_crtc = to_exynos_crtc(old_state->crtc); - decon = exynos_crtc->ctx; - /* - * Currently requested zpos(window) can NOT disabled even if window is - * used previously. - */ - if ((exynos_crtc->ops->disable_plane) && (dpp->win_id < MAX_PLANE) && - !test_bit(dpp->win_id, &decon->req_windows)) - exynos_crtc->ops->disable_plane(exynos_crtc, exynos_plane); + if (old_state->visible) + exynos_plane_disable(plane, old_state->crtc); } static const struct drm_plane_helper_funcs plane_helper_funcs = { |