summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiun Yu <jiun.yu@samsung.com>2019-12-08 10:14:52 +0900
committerAdrian Salido <salidoa@google.com>2020-09-29 13:59:17 -0700
commit826e799777079f1a5f8a7b59eaf6bfc9b72d5a44 (patch)
treedc78e594e4c86932db5a1481906a4ae70ac4cd38
parentf232dce7444037f0e9278086afd59852a21d097f (diff)
downloaddisplay-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.c3
-rw-r--r--samsung/exynos_drm_decon.c5
-rw-r--r--samsung/exynos_drm_decon.h3
-rw-r--r--samsung/exynos_drm_fb.c2
-rw-r--r--samsung/exynos_drm_plane.c74
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 = {