Commit 99cf4a29 authored by Daniel Stone's avatar Daniel Stone Committed by Daniel Vetter

drm/atomic: Add current-mode blob to CRTC state

Add a blob property tracking the current mode to the CRTC state, and
ensure it is properly updated and referenced.

v2: Continue using crtc_state->mode inside getcrtc, instead of reading
    out the mode blob. Use IS_ERR and PTR_ERR from create_blob. Move
    set_mode_prop_for_crtc to later patch where it actually gets used.
    Enforce !!state->enable == !!state->mode_blob inside
    drm_atomic_crtc_check.
Signed-off-by: default avatarDaniel Stone <daniels@collabora.com>
Tested-by: default avatarSean Paul <seanpaul@chromium.org>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 819364da
...@@ -304,11 +304,25 @@ EXPORT_SYMBOL(drm_atomic_get_crtc_state); ...@@ -304,11 +304,25 @@ EXPORT_SYMBOL(drm_atomic_get_crtc_state);
int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_mode_modeinfo umode;
/* Early return for no change. */ /* Early return for no change. */
if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0) if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
return 0; return 0;
if (state->mode_blob)
drm_property_unreference_blob(state->mode_blob);
state->mode_blob = NULL;
if (mode) { if (mode) {
drm_mode_convert_to_umode(&umode, mode);
state->mode_blob =
drm_property_create_blob(state->crtc->dev,
sizeof(umode),
&umode);
if (IS_ERR(state->mode_blob))
return PTR_ERR(state->mode_blob);
drm_mode_copy(&state->mode, mode); drm_mode_copy(&state->mode, mode);
state->enable = true; state->enable = true;
DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n", DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
...@@ -324,7 +338,6 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state, ...@@ -324,7 +338,6 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
} }
EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc); EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
/** /**
* drm_atomic_crtc_set_property - set property on CRTC * drm_atomic_crtc_set_property - set property on CRTC
* @crtc: the drm CRTC to set a property on * @crtc: the drm CRTC to set a property on
...@@ -410,6 +423,23 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc, ...@@ -410,6 +423,23 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
return -EINVAL; return -EINVAL;
} }
/* The state->enable vs. state->mode_blob checks can be WARN_ON,
* as this is a kernel-internal detail that userspace should never
* be able to trigger. */
if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
WARN_ON(state->enable && !state->mode_blob)) {
DRM_DEBUG_ATOMIC("[CRTC:%d] enabled without mode blob\n",
crtc->base.id);
return -EINVAL;
}
if (drm_core_check_feature(crtc->dev, DRIVER_ATOMIC) &&
WARN_ON(!state->enable && state->mode_blob)) {
DRM_DEBUG_ATOMIC("[CRTC:%d] disabled with mode blob\n",
crtc->base.id);
return -EINVAL;
}
return 0; return 0;
} }
......
...@@ -2044,6 +2044,8 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); ...@@ -2044,6 +2044,8 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
*/ */
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
{ {
if (crtc->state && crtc->state->mode_blob)
drm_property_unreference_blob(crtc->state->mode_blob);
kfree(crtc->state); kfree(crtc->state);
crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
...@@ -2065,6 +2067,8 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, ...@@ -2065,6 +2067,8 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
{ {
memcpy(state, crtc->state, sizeof(*state)); memcpy(state, crtc->state, sizeof(*state));
if (state->mode_blob)
drm_property_reference_blob(state->mode_blob);
state->mode_changed = false; state->mode_changed = false;
state->active_changed = false; state->active_changed = false;
state->planes_changed = false; state->planes_changed = false;
...@@ -2107,11 +2111,8 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); ...@@ -2107,11 +2111,8 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state) struct drm_crtc_state *state)
{ {
/* if (state->mode_blob)
* This is currently a placeholder so that drivers that subclass the drm_property_unreference_blob(state->mode_blob);
* state will automatically do the right thing if code is ever added
* to this function.
*/
} }
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
......
...@@ -299,6 +299,9 @@ struct drm_crtc_state { ...@@ -299,6 +299,9 @@ struct drm_crtc_state {
struct drm_display_mode mode; struct drm_display_mode mode;
/* blob property to expose current mode to atomic userspace */
struct drm_property_blob *mode_blob;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
struct drm_atomic_state *state; struct drm_atomic_state *state;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment