diff --git a/msm/msm_atomic.c b/msm/msm_atomic.c index f4e4dea170..1d1447b54b 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 a88ccef07f..537ae164d7 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -941,6 +942,93 @@ 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; + 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) { + crtc = connector->state->crtc ? connector->state->crtc : + old_conn_state->crtc; + if (!crtc) + continue; + + 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); + + 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; + + 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); + + /* 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; + + 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) { @@ -1081,6 +1169,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"); } @@ -1419,6 +1508,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);