summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2015-01-22 18:53:05 +0100
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-01-22 19:33:09 +0100
commit35b219a1ca6ac3a89ee06dae5b4e73900eeab94c (patch)
treef24562b74a413aa126166c2aad70c159e4af4186
parent5b4b84ca1db658891ac8cecd9b9fed6227b1755f (diff)
drm/atomic-helper: add connector->dpms() implementation
This builds on top of the crtc->active infrastructure to implement legacy DPMS. My choice of semantics is somewhat arbitrary, but the entire pipe is enabled as along as one output is still enabled. Of course it also clamps everything that's not ON to OFF. v2: Fix spelling in one comment. v3: Don't do an async commit (Thierry) Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c75
-rw-r--r--include/drm/drm_atomic_helper.h2
2 files changed, 77 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 3f17933b1d2c..f693344d9573 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1887,6 +1887,81 @@ backoff:
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);
+
+ 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
*
* Both the drm core and the atomic helpers assume that there is always the full
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 2095917ff8c7..cf501df9e513 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -82,6 +82,8 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t flags);
+void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
+ int mode);
/* default implementations for state handling */
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);