mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: Daniel Stone <daniels@collabora.com>
Tested-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
			
			
This commit is contained in:
		
							parent
							
								
									819364da20
								
							
						
					
					
						commit
						99cf4a29fa
					
				
					 3 changed files with 40 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -304,11 +304,25 @@ EXPORT_SYMBOL(drm_atomic_get_crtc_state);
 | 
			
		|||
int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
 | 
			
		||||
				 struct drm_display_mode *mode)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_mode_modeinfo umode;
 | 
			
		||||
 | 
			
		||||
	/* Early return for no change. */
 | 
			
		||||
	if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (state->mode_blob)
 | 
			
		||||
		drm_property_unreference_blob(state->mode_blob);
 | 
			
		||||
	state->mode_blob = NULL;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
		state->enable = true;
 | 
			
		||||
		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,
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_atomic_set_mode_for_crtc);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * drm_atomic_crtc_set_property - set property on CRTC
 | 
			
		||||
 * @crtc: the drm CRTC to set a property on
 | 
			
		||||
| 
						 | 
				
			
			@ -410,6 +423,23 @@ static int drm_atomic_crtc_check(struct drm_crtc *crtc,
 | 
			
		|||
		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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2044,6 +2044,8 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
 | 
			
		|||
 */
 | 
			
		||||
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);
 | 
			
		||||
	crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2065,6 +2067,8 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
 | 
			
		|||
{
 | 
			
		||||
	memcpy(state, crtc->state, sizeof(*state));
 | 
			
		||||
 | 
			
		||||
	if (state->mode_blob)
 | 
			
		||||
		drm_property_reference_blob(state->mode_blob);
 | 
			
		||||
	state->mode_changed = false;
 | 
			
		||||
	state->active_changed = false;
 | 
			
		||||
	state->planes_changed = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -2107,11 +2111,8 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
 | 
			
		|||
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
 | 
			
		||||
					    struct drm_crtc_state *state)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * This is currently a placeholder so that drivers that subclass the
 | 
			
		||||
	 * state will automatically do the right thing if code is ever added
 | 
			
		||||
	 * to this function.
 | 
			
		||||
	 */
 | 
			
		||||
	if (state->mode_blob)
 | 
			
		||||
		drm_property_unreference_blob(state->mode_blob);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -299,6 +299,9 @@ struct drm_crtc_state {
 | 
			
		|||
 | 
			
		||||
	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_atomic_state *state;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue