diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic_helper.c')
| -rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 63 | 
1 files changed, 59 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index d579fd8f7cb8..2c2c9caf0be5 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1511,6 +1511,47 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,  }  EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables); +/* + * For atomic updates which touch just a single CRTC, calculate the time of the + * next vblank, and inform all the fences of the deadline. + */ +static void set_fence_deadline(struct drm_device *dev, +			       struct drm_atomic_state *state) +{ +	struct drm_crtc *crtc; +	struct drm_crtc_state *new_crtc_state; +	struct drm_plane *plane; +	struct drm_plane_state *new_plane_state; +	ktime_t vbltime = 0; +	int i; + +	for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { +		ktime_t v; + +		if (drm_atomic_crtc_needs_modeset(new_crtc_state)) +			continue; + +		if (!new_crtc_state->active) +			continue; + +		if (drm_crtc_next_vblank_start(crtc, &v)) +			continue; + +		if (!vbltime || ktime_before(v, vbltime)) +			vbltime = v; +	} + +	/* If no CRTCs updated, then nothing to do: */ +	if (!vbltime) +		return; + +	for_each_new_plane_in_state (state, plane, new_plane_state, i) { +		if (!new_plane_state->fence) +			continue; +		dma_fence_set_deadline(new_plane_state->fence, vbltime); +	} +} +  /**   * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state   * @dev: DRM device @@ -1540,6 +1581,8 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev,  	struct drm_plane_state *new_plane_state;  	int i, ret; +	set_fence_deadline(dev, state); +  	for_each_new_plane_in_state(state, plane, new_plane_state, i) {  		if (!new_plane_state->fence)  			continue; @@ -2702,6 +2745,11 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,  			funcs->atomic_disable(plane, old_state);  		} else if (new_plane_state->crtc || disabling) {  			funcs->atomic_update(plane, old_state); + +			if (!disabling && funcs->atomic_enable) { +				if (drm_atomic_plane_enabling(old_plane_state, new_plane_state)) +					funcs->atomic_enable(plane, old_state); +			}  		}  	} @@ -2762,6 +2810,7 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)  		struct drm_plane_state *new_plane_state =  			drm_atomic_get_new_plane_state(old_state, plane);  		const struct drm_plane_helper_funcs *plane_funcs; +		bool disabling;  		plane_funcs = plane->helper_private; @@ -2771,12 +2820,18 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)  		WARN_ON(new_plane_state->crtc &&  			new_plane_state->crtc != crtc); -		if (drm_atomic_plane_disabling(old_plane_state, new_plane_state) && -		    plane_funcs->atomic_disable) +		disabling = drm_atomic_plane_disabling(old_plane_state, new_plane_state); + +		if (disabling && plane_funcs->atomic_disable) {  			plane_funcs->atomic_disable(plane, old_state); -		else if (new_plane_state->crtc || -			 drm_atomic_plane_disabling(old_plane_state, new_plane_state)) +		} else if (new_plane_state->crtc || disabling) {  			plane_funcs->atomic_update(plane, old_state); + +			if (!disabling && plane_funcs->atomic_enable) { +				if (drm_atomic_plane_enabling(old_plane_state, new_plane_state)) +					plane_funcs->atomic_enable(plane, old_state); +			} +		}  	}  	if (crtc_funcs && crtc_funcs->atomic_flush)  |