|
@@ -1886,6 +1886,83 @@ backoff:
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(drm_atomic_helper_page_flip);
|
|
EXPORT_SYMBOL(drm_atomic_helper_page_flip);
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * drm_atomic_helper_connector_dpms() - connector dpms helper implementation
|
|
|
|
+ * @connector: affected connector
|
|
|
|
+ * @mode: DPMS mode
|
|
|
|
+ *
|
|
|
|
+ * This is the main helper function provided by the atomic helper framework for
|
|
|
|
+ * implementing the legacy DPMS connector interface. It computes the new desired
|
|
|
|
+ * ->active state for the corresponding CRTC (if the connector is enabled) and
|
|
|
|
+ * updates it.
|
|
|
|
+ */
|
|
|
|
+void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
|
|
|
|
+ int mode)
|
|
|
|
+{
|
|
|
|
+ struct drm_mode_config *config = &connector->dev->mode_config;
|
|
|
|
+ struct drm_atomic_state *state;
|
|
|
|
+ struct drm_crtc_state *crtc_state;
|
|
|
|
+ struct drm_crtc *crtc;
|
|
|
|
+ struct drm_connector *tmp_connector;
|
|
|
|
+ int ret;
|
|
|
|
+ bool active = false;
|
|
|
|
+
|
|
|
|
+ if (mode != DRM_MODE_DPMS_ON)
|
|
|
|
+ mode = DRM_MODE_DPMS_OFF;
|
|
|
|
+
|
|
|
|
+ connector->dpms = mode;
|
|
|
|
+ crtc = connector->state->crtc;
|
|
|
|
+
|
|
|
|
+ if (!crtc)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ /* FIXME: ->dpms has no return value so can't forward the -ENOMEM. */
|
|
|
|
+ state = drm_atomic_state_alloc(connector->dev);
|
|
|
|
+ if (!state)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
|
|
|
+retry:
|
|
|
|
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
|
|
|
+ if (IS_ERR(crtc_state))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(tmp_connector, &config->connector_list, head) {
|
|
|
|
+ if (connector->state->crtc != crtc)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (connector->dpms == DRM_MODE_DPMS_ON) {
|
|
|
|
+ active = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ crtc_state->active = active;
|
|
|
|
+
|
|
|
|
+ ret = drm_atomic_commit(state);
|
|
|
|
+ if (ret != 0)
|
|
|
|
+ goto fail;
|
|
|
|
+
|
|
|
|
+ /* Driver takes ownership of state on successful async commit. */
|
|
|
|
+ return;
|
|
|
|
+fail:
|
|
|
|
+ if (ret == -EDEADLK)
|
|
|
|
+ goto backoff;
|
|
|
|
+
|
|
|
|
+ drm_atomic_state_free(state);
|
|
|
|
+
|
|
|
|
+ WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret);
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+backoff:
|
|
|
|
+ drm_atomic_state_clear(state);
|
|
|
|
+ drm_atomic_legacy_backoff(state);
|
|
|
|
+
|
|
|
|
+ goto retry;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* DOC: atomic state reset and initialization
|
|
* DOC: atomic state reset and initialization
|
|
*
|
|
*
|