summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Salido <salidoa@google.com>2023-03-03 14:01:08 -0800
committerKen Huang <kenbshuang@google.com>2023-12-21 20:01:32 +0800
commit296f51170246be8d85fb3c25f1bc0462a09b3588 (patch)
tree87b21ed75d3c5a5aa71cdd77100e45f014f844ec
parent6ca3474924c4a902f425660d5b5db90a3918078a (diff)
downloaddisplay-296f51170246be8d85fb3c25f1bc0462a09b3588.tar.gz
drm: samsung: change tui sequence for video mode
Bug: 270193879 Bug: 232723067 Change-Id: Icef95f24bb1b4906d8187fa530ada17785010091 Signed-off-by: Adrian Salido <salidoa@google.com> (cherry picked from commit b7d23df08a4f09a50198b49c8a8ac4474c9c1551)
-rw-r--r--samsung/exynos_drm_drv.c57
-rw-r--r--samsung/panel/panel-samsung-drv.c6
2 files changed, 37 insertions, 26 deletions
diff --git a/samsung/exynos_drm_drv.c b/samsung/exynos_drm_drv.c
index ac0df79..ba8917d 100644
--- a/samsung/exynos_drm_drv.c
+++ b/samsung/exynos_drm_drv.c
@@ -723,10 +723,9 @@ int exynos_atomic_enter_tui(void)
struct drm_plane *plane;
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
- struct drm_connector *conn;
- struct drm_connector_state *conn_state;
u32 tui_crtc_mask = 0;
struct exynos_drm_private *private = drm_to_exynos_dev(dev);
+ struct exynos_drm_connector_state *exynos_conn_state;
pr_debug("%s +\n", __func__);
@@ -755,8 +754,6 @@ int exynos_atomic_enter_tui(void)
state->acquire_ctx = &ctx;
drm_for_each_crtc(crtc, dev) {
- struct exynos_drm_crtc_state *exynos_crtc_state;
-
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
@@ -766,14 +763,10 @@ int exynos_atomic_enter_tui(void)
if (!crtc_state->enable || !crtc_state->active)
continue;
- exynos_crtc_state = to_exynos_crtc_state(crtc_state);
+ decon = crtc_to_decon(crtc);
+ /* get an extra ref count while in TUI, to keep power domain active */
+ pm_runtime_get_sync(decon->dev);
- exynos_crtc_state->bypass = true;
- /*
- * set crtc in self refresh, this will keep power/regulators
- * enabled but disable everything else
- */
- crtc_state->self_refresh_active = true;
crtc_state->active = false;
tui_crtc_mask |= drm_crtc_mask(crtc);
@@ -784,6 +777,19 @@ int exynos_atomic_enter_tui(void)
ret = drm_atomic_add_affected_connectors(state, crtc);
if (ret)
goto err;
+
+ exynos_conn_state = crtc_get_exynos_connector_state(state, crtc_state);
+ if (exynos_conn_state) {
+ exynos_conn_state->blanked_mode = true;
+
+ if (exynos_conn_state->base.self_refresh_aware) {
+ struct exynos_drm_crtc_state *exynos_crtc_state =
+ to_exynos_crtc_state(crtc_state);
+
+ exynos_crtc_state->bypass = true;
+ crtc_state->self_refresh_active = true;
+ }
+ }
}
if (!tui_crtc_mask) {
@@ -792,20 +798,6 @@ int exynos_atomic_enter_tui(void)
goto err;
}
- for_each_new_connector_in_state(state, conn, conn_state, i) {
- if (!conn_state->self_refresh_aware &&
- (conn->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)) {
- pr_warn("%s: %s doesn't support self refresh\n", __func__, conn->name);
- goto err;
- }
- if (is_exynos_drm_connector(conn)) {
- struct exynos_drm_connector_state *exynos_conn_state =
- to_exynos_connector_state(conn_state);
-
- exynos_conn_state->blanked_mode = true;
- }
- }
-
for_each_new_plane_in_state(state, plane, plane_state, i) {
ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
if (ret < 0)
@@ -836,6 +828,10 @@ err_dup:
drm_for_each_crtc(crtc, dev) {
decon = crtc_to_decon(crtc);
hibernation_unblock_enter(decon->hibernation);
+
+ /* remove pm refs on failure */
+ if (ret && (tui_crtc_mask & drm_crtc_mask(crtc)))
+ pm_runtime_put_sync(decon->dev);
}
return ret;
@@ -850,6 +846,9 @@ int exynos_atomic_exit_tui(void)
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_modeset_acquire_ctx ctx;
struct exynos_drm_private *private = drm_to_exynos_dev(dev);
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ int i;
pr_debug("%s +\n", __func__);
@@ -876,6 +875,14 @@ int exynos_atomic_exit_tui(void)
else
mode_config->suspend_state = NULL;
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc_state->active) {
+ decon = crtc_to_decon(crtc);
+ /* drop the ref taken during enter tui */
+ pm_runtime_put_sync(decon->dev);
+ }
+ }
+
DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
if (!ret)
drm_atomic_state_put(state);
diff --git a/samsung/panel/panel-samsung-drv.c b/samsung/panel/panel-samsung-drv.c
index d9d7d7d..2ce01ba 100644
--- a/samsung/panel/panel-samsung-drv.c
+++ b/samsung/panel/panel-samsung-drv.c
@@ -2385,11 +2385,16 @@ static int exynos_drm_connector_check_mode(struct exynos_panel *ctx,
to_exynos_connector_state(connector_state);
const struct exynos_panel_mode *pmode =
exynos_panel_get_mode(ctx, &crtc_state->mode);
+ bool is_video_mode;
if (!pmode) {
dev_warn(ctx->dev, "invalid mode %s\n", crtc_state->mode.name);
return -EINVAL;
}
+ is_video_mode = (pmode->exynos_mode.mode_flags & MIPI_DSI_MODE_VIDEO) != 0;
+
+ /* self refresh is only supported in command mode */
+ connector_state->self_refresh_aware = !is_video_mode;
if (crtc_state->connectors_changed || !is_panel_active(ctx))
exynos_connector_state->seamless_possible = false;
@@ -3597,7 +3602,6 @@ static int exynos_panel_bridge_attach(struct drm_bridge *bridge,
drm_connector_attach_encoder(connector, bridge->encoder);
connector->funcs->reset(connector);
connector->status = connector_status_connected;
- connector->state->self_refresh_aware = true;
if (ctx->desc->exynos_panel_func && ctx->desc->exynos_panel_func->commit_done)
ctx->exynos_connector.needs_commit = true;