From fb50dda175fa6b748fd7eedd34d5321d6081a710 Mon Sep 17 00:00:00 2001 From: Adrian Salido Date: Wed, 23 Oct 2019 13:56:50 -0700 Subject: [PATCH 1/3] disp: msm: add low power mode notifier Introduce low power mode so that listeners are aware when display is going into low power mode. This requires moving notifier inside sde code to be able to retrieve the low power state. Change-Id: I8671e86af29c959d97e1b8ad758a07719ffa4bec (cherry picked from commit c4b15f56dd63d24d6f4482deab2423809c700d7a) Signed-off-by: Adrian Salido [samtran@codeaurora.org: move changes to different file as downstream use of notifier struct comes from different file] Signed-off-by: Samantha Tran Signed-off-by: Dhaval Patel Signed-off-by: Narendra Muppalla --- msm/msm_atomic.c | 46 ++-------------------------- msm/sde/sde_kms.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 44 deletions(-) diff --git a/msm/msm_atomic.c b/msm/msm_atomic.c index 0a2f95e48b..7980303241 100644 --- a/msm/msm_atomic.c +++ b/msm/msm_atomic.c @@ -184,8 +184,7 @@ msm_disable_connector_outputs(struct drm_device *dev, { struct drm_connector *connector; struct drm_connector_state *old_conn_state; - struct drm_panel_notifier notifier_data; - int i, blank; + int i; for_each_old_connector_in_state(old_state, connector, old_conn_state, i) { @@ -223,15 +222,6 @@ msm_disable_connector_outputs(struct drm_device *dev, DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n", encoder->base.id, encoder->name); - if (connector->state->crtc && - connector->state->crtc->state->active_changed) { - blank = DRM_PANEL_BLANK_POWERDOWN; - notifier_data.data = ␣ - if (connector->panel) - drm_panel_notifier_call_chain(connector->panel, - DRM_PANEL_EARLY_EVENT_BLANK, - ¬ifier_data); - } /* * Each encoder has at most one connector (since we always steal * it away), so we won't call disable hooks twice. @@ -247,14 +237,6 @@ msm_disable_connector_outputs(struct drm_device *dev, funcs->dpms(encoder, DRM_MODE_DPMS_OFF); drm_bridge_post_disable(encoder->bridge); - if (connector->state->crtc && - connector->state->crtc->state->active_changed) { - DRM_DEBUG_ATOMIC("Notify blank\n"); - if (connector->panel) - drm_panel_notifier_call_chain(connector->panel, - DRM_PANEL_EVENT_BLANK, - ¬ifier_data); - } } } @@ -410,12 +392,10 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, struct drm_crtc_state *new_crtc_state; struct drm_connector *connector; struct drm_connector_state *new_conn_state; - struct drm_panel_notifier notifier_data; struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; int bridge_enable_count = 0; - int i, blank; - bool splash = false; + int i; SDE_ATRACE_BEGIN("msm_enable"); for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, @@ -475,19 +455,6 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n", encoder->base.id, encoder->name); - if (kms && kms->funcs && kms->funcs->check_for_splash) - splash = kms->funcs->check_for_splash(kms); - - if (splash || (connector->state->crtc && - connector->state->crtc->state->active_changed)) { - blank = DRM_PANEL_BLANK_UNBLANK; - notifier_data.data = ␣ - DRM_DEBUG_ATOMIC("Notify early unblank\n"); - if (connector->panel) - drm_panel_notifier_call_chain(connector->panel, - DRM_PANEL_EARLY_EVENT_BLANK, - ¬ifier_data); - } /* * Each encoder has at most one connector (since we always steal * it away), so we won't call enable hooks twice. @@ -536,15 +503,6 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, encoder->base.id, encoder->name); drm_bridge_enable(encoder->bridge); - - if (splash || (connector->state->crtc && - connector->state->crtc->state->active_changed)) { - DRM_DEBUG_ATOMIC("Notify unblank\n"); - if (connector->panel) - drm_panel_notifier_call_chain(connector->panel, - DRM_PANEL_EVENT_BLANK, - ¬ifier_data); - } } SDE_ATRACE_END("msm_enable"); } diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 4773b58e5f..2da651445e 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -939,6 +940,80 @@ static int _sde_kms_unmap_all_splash_regions(struct sde_kms *sde_kms) return ret; } +static int _sde_kms_get_blank(struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + int lp_mode, blank; + + if (crtc_state->active) + lp_mode = sde_connector_get_property(conn_state, + CONNECTOR_PROP_LP); + else + lp_mode = SDE_MODE_DPMS_OFF; + + switch (lp_mode) { + case SDE_MODE_DPMS_ON: + blank = DRM_PANEL_BLANK_UNBLANK; + break; + case SDE_MODE_DPMS_LP1: + case SDE_MODE_DPMS_LP2: + blank = DRM_PANEL_BLANK_LP; + break; + case SDE_MODE_DPMS_OFF: + default: + blank = DRM_PANEL_BLANK_POWERDOWN; + break; + } + + return blank; +} + +static void _sde_kms_drm_check_dpms(struct drm_atomic_state *old_state, + unsigned long event) +{ + struct drm_connector *connector; + struct drm_connector_state *old_conn_state; + struct drm_crtc_state *old_crtc_state; + int i, old_mode, new_mode, old_fps, new_fps; + + for_each_old_connector_in_state(old_state, connector, + old_conn_state, i) { + if (!connector->state->crtc) + continue; + + new_fps = connector->state->crtc->state->mode.vrefresh; + new_mode = _sde_kms_get_blank(connector->state->crtc->state, + connector->state); + if (old_conn_state->crtc) { + old_crtc_state = drm_atomic_get_existing_crtc_state( + old_state, old_conn_state->crtc); + + old_fps = old_crtc_state->mode.vrefresh; + old_mode = _sde_kms_get_blank(old_crtc_state, + old_conn_state); + } else { + old_fps = 0; + old_mode = DRM_PANEL_BLANK_POWERDOWN; + } + + if ((old_mode != new_mode) || (old_fps != new_fps)) { + struct drm_panel_notifier notifier_data; + + pr_debug("change detected (power mode %d->%d, fps %d->%d)\n", + old_mode, new_mode, old_fps, new_fps); + + notifier_data.data = &new_mode; + notifier_data.refresh_rate = new_fps; + notifier_data.id = connector->base.id; + + if (connector->panel) + drm_panel_notifier_call_chain(connector->panel, + event, ¬ifier_data); + } + } + +} + int sde_kms_vm_primary_prepare_commit(struct sde_kms *sde_kms, struct drm_atomic_state *state) { @@ -1079,6 +1154,7 @@ static void sde_kms_prepare_commit(struct msm_kms *kms, if (vm_ops->vm_prepare_commit) vm_ops->vm_prepare_commit(sde_kms, state); + _sde_kms_drm_check_dpms(state, DRM_PANEL_EARLY_EVENT_BLANK); end: SDE_ATRACE_END("prepare_commit"); } @@ -1417,6 +1493,7 @@ static void sde_kms_complete_commit(struct msm_kms *kms, SDE_ERROR("vm post commit failed, rc = %d\n", rc); } + _sde_kms_drm_check_dpms(old_state, DRM_PANEL_EVENT_BLANK); pm_runtime_put_sync(sde_kms->dev->dev); From 2b492f05d9f30b464b227e665e6feb11b93f28ca Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Tue, 26 Nov 2019 15:43:33 +0530 Subject: [PATCH 2/3] disp: msm: add new mode to notify when there is a fps change Add a new mode DRM_PANEL_BLANK_FPS_CHANGE whenever there is a change in fps and the power mode remains the same. This will avoid unnecessary resume operations in touch driver. Change-Id: Id3d5884ba862c864782636360e3832854464bf65 Signed-off-by: Krishna Manikandan --- msm/sde/sde_kms.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 2da651445e..6e771c5188 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1002,6 +1002,14 @@ static void _sde_kms_drm_check_dpms(struct drm_atomic_state *old_state, pr_debug("change detected (power mode %d->%d, fps %d->%d)\n", old_mode, new_mode, old_fps, new_fps); + /* If suspend resume and fps change are happening + * at the same time, give preference to power mode + * changes rather than fps change. + */ + + if ((old_mode == new_mode) && (old_fps != new_fps)) + new_mode = DRM_PANEL_BLANK_FPS_CHANGE; + notifier_data.data = &new_mode; notifier_data.refresh_rate = new_fps; notifier_data.id = connector->base.id; From 66d9e1e9abc97328c313f0aa5a85f9dcea89d1e6 Mon Sep 17 00:00:00 2001 From: Raviteja Tamatam Date: Tue, 24 Dec 2019 14:25:46 +0530 Subject: [PATCH 3/3] disp: msm: sde: update crtc check in drm_check_dpms In cases of adb shell stop, connector->state->crtc is not updated which prevents panel power down notification to be sent. In such cases updated crtc from old connector state. Change-Id: I94f9e5ad469d771cc673123b4e0cc65ea8f4653e Signed-off-by: Raviteja Tamatam Signed-off-by: Narendra Muppalla --- msm/sde/sde_kms.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 6e771c5188..7bc66dc3dc 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -974,16 +974,18 @@ static void _sde_kms_drm_check_dpms(struct drm_atomic_state *old_state, struct drm_connector *connector; struct drm_connector_state *old_conn_state; struct drm_crtc_state *old_crtc_state; + struct drm_crtc *crtc; int i, old_mode, new_mode, old_fps, new_fps; for_each_old_connector_in_state(old_state, connector, old_conn_state, i) { - if (!connector->state->crtc) + crtc = connector->state->crtc ? connector->state->crtc : + old_conn_state->crtc; + if (!crtc) continue; - new_fps = connector->state->crtc->state->mode.vrefresh; - new_mode = _sde_kms_get_blank(connector->state->crtc->state, - connector->state); + new_fps = crtc->state->mode.vrefresh; + new_mode = _sde_kms_get_blank(crtc->state, connector->state); if (old_conn_state->crtc) { old_crtc_state = drm_atomic_get_existing_crtc_state( old_state, old_conn_state->crtc); @@ -999,6 +1001,9 @@ static void _sde_kms_drm_check_dpms(struct drm_atomic_state *old_state, if ((old_mode != new_mode) || (old_fps != new_fps)) { struct drm_panel_notifier notifier_data; + SDE_EVT32(old_mode, new_mode, old_fps, new_fps, + connector->panel, crtc->state->active, + old_conn_state->crtc, event); pr_debug("change detected (power mode %d->%d, fps %d->%d)\n", old_mode, new_mode, old_fps, new_fps);