diff options
author | Adrian Salido <salidoa@google.com> | 2023-03-03 14:01:08 -0800 |
---|---|---|
committer | Oleg Matcovschi <omatcovschi@google.com> | 2023-03-24 19:03:12 +0000 |
commit | b7d23df08a4f09a50198b49c8a8ac4474c9c1551 (patch) | |
tree | 983dffa81ad6fe453b346ebee5af051c01e1b543 | |
parent | 695c742131a1ff3305709f967bbe69a741733650 (diff) | |
download | display-b7d23df08a4f09a50198b49c8a8ac4474c9c1551.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>
-rw-r--r-- | samsung/exynos_drm_drv.c | 57 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-drv.c | 6 |
2 files changed, 37 insertions, 26 deletions
diff --git a/samsung/exynos_drm_drv.c b/samsung/exynos_drm_drv.c index 081406d..5405fe7 100644 --- a/samsung/exynos_drm_drv.c +++ b/samsung/exynos_drm_drv.c @@ -669,10 +669,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__); @@ -701,8 +700,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); @@ -712,14 +709,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); @@ -730,6 +723,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) { @@ -738,20 +744,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) @@ -782,6 +774,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; @@ -796,6 +792,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__); @@ -822,6 +821,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 593e1d3..eba999e 100644 --- a/samsung/panel/panel-samsung-drv.c +++ b/samsung/panel/panel-samsung-drv.c @@ -1971,11 +1971,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", pmode->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; @@ -3175,7 +3180,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; |