Skip to content

Commit

Permalink
drm/atomic-helper: add connector->dpms() implementation
Browse files Browse the repository at this point in the history
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)

v4: Dan Carpenter noticed missing error case handling.

Cc: Thierry Reding <thierry.reding@gmail.com>
Reviewed-by: Thierry Reding <treding@nvidia.com>
Tested-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
  • Loading branch information
Daniel Vetter committed Jan 27, 2015
1 parent eab3bbe commit b486e0e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
77 changes: 77 additions & 0 deletions drivers/gpu/drm/drm_atomic_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1886,6 +1886,83 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
}
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
*
Expand Down
2 changes: 2 additions & 0 deletions include/drm/drm_atomic_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit b486e0e

Please sign in to comment.