diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_fbc.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_fbc.c | 115 | 
1 files changed, 61 insertions, 54 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 87f4af3fd523..bbdc34a23d54 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -38,9 +38,12 @@   * forcibly disable it to allow proper screen updates.   */ +#include <linux/string_helpers.h> +  #include <drm/drm_fourcc.h>  #include "i915_drv.h" +#include "i915_utils.h"  #include "i915_vgpu.h"  #include "intel_cdclk.h"  #include "intel_de.h" @@ -87,7 +90,6 @@ struct intel_fbc {  	 * with stolen_lock.  	 */  	struct mutex lock; -	unsigned int possible_framebuffer_bits;  	unsigned int busy_bits;  	struct drm_mm_node compressed_fb; @@ -665,6 +667,10 @@ static bool intel_fbc_is_compressing(struct intel_fbc *fbc)  static void intel_fbc_nuke(struct intel_fbc *fbc)  { +	struct drm_i915_private *i915 = fbc->i915; + +	drm_WARN_ON(&i915->drm, fbc->flip_pending); +  	trace_intel_fbc_nuke(fbc->state.plane);  	fbc->funcs->nuke(fbc); @@ -805,6 +811,14 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc)  	fbc->funcs->program_cfb(fbc);  } +static void intel_fbc_program_workarounds(struct intel_fbc *fbc) +{ +	/* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,dg2,adlp */ +	if (DISPLAY_VER(fbc->i915) >= 11) +		intel_de_rmw(fbc->i915, ILK_DPFC_CHICKEN(fbc->id), 0, +			     DPFC_CHICKEN_FORCE_SLB_INVALIDATION); +} +  static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc)  {  	struct drm_i915_private *i915 = fbc->i915; @@ -946,6 +960,7 @@ static bool tiling_is_valid(const struct intel_plane_state *plane_state)  	case I915_FORMAT_MOD_Y_TILED:  	case I915_FORMAT_MOD_Yf_TILED:  		return DISPLAY_VER(i915) >= 9; +	case I915_FORMAT_MOD_4_TILED:  	case I915_FORMAT_MOD_X_TILED:  		return true;  	default: @@ -966,6 +981,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,  	struct intel_fbc_state *fbc_state = &fbc->state;  	WARN_ON(plane_state->no_fbc_reason); +	WARN_ON(fbc_state->plane && fbc_state->plane != plane);  	fbc_state->plane = plane; @@ -1037,7 +1053,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,  	struct intel_plane_state *plane_state =  		intel_atomic_get_new_plane_state(state, plane);  	const struct drm_framebuffer *fb = plane_state->hw.fb; -	struct intel_crtc *crtc = to_intel_crtc(plane_state->uapi.crtc); +	struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc);  	const struct intel_crtc_state *crtc_state;  	struct intel_fbc *fbc = plane->fbc; @@ -1078,7 +1094,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,  	 */  	if (DISPLAY_VER(i915) >= 12 && crtc_state->has_psr2) {  		plane_state->no_fbc_reason = "PSR2 enabled"; -		return false; +		return 0;  	}  	if (!pixel_format_is_valid(plane_state)) { @@ -1104,7 +1120,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,  	if (plane_state->hw.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE &&  	    fb->format->has_alpha) {  		plane_state->no_fbc_reason = "per-pixel alpha not supported"; -		return false; +		return 0;  	}  	if (!intel_fbc_hw_tracking_covers_screen(plane_state)) { @@ -1120,7 +1136,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,  	if (DISPLAY_VER(i915) >= 9 &&  	    plane_state->view.color_plane[0].y & 3) {  		plane_state->no_fbc_reason = "plane start Y offset misaligned"; -		return false; +		return 0;  	}  	/* Wa_22010751166: icl, ehl, tgl, dg1, rkl */ @@ -1128,7 +1144,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,  	    (plane_state->view.color_plane[0].y +  	     (drm_rect_height(&plane_state->uapi.src) >> 16)) & 3) {  		plane_state->no_fbc_reason = "plane end Y offset misaligned"; -		return false; +		return 0;  	}  	/* WaFbcExceedCdClockThreshold:hsw,bdw */ @@ -1270,6 +1286,8 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)  	__intel_fbc_cleanup_cfb(fbc);  	fbc->state.plane = NULL; +	fbc->flip_pending = false; +	fbc->busy_bits = 0;  }  static void __intel_fbc_post_update(struct intel_fbc *fbc) @@ -1313,7 +1331,7 @@ static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc)  	if (fbc->state.plane)  		return fbc->state.plane->frontbuffer_bit;  	else -		return fbc->possible_framebuffer_bits; +		return 0;  }  static void __intel_fbc_invalidate(struct intel_fbc *fbc, @@ -1325,11 +1343,14 @@ static void __intel_fbc_invalidate(struct intel_fbc *fbc,  	mutex_lock(&fbc->lock); -	fbc->busy_bits |= intel_fbc_get_frontbuffer_bit(fbc) & frontbuffer_bits; +	frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc); +	if (!frontbuffer_bits) +		goto out; -	if (fbc->state.plane && fbc->busy_bits) -		intel_fbc_deactivate(fbc, "frontbuffer write"); +	fbc->busy_bits |= frontbuffer_bits; +	intel_fbc_deactivate(fbc, "frontbuffer write"); +out:  	mutex_unlock(&fbc->lock);  } @@ -1351,18 +1372,22 @@ static void __intel_fbc_flush(struct intel_fbc *fbc,  {  	mutex_lock(&fbc->lock); +	frontbuffer_bits &= intel_fbc_get_frontbuffer_bit(fbc); +	if (!frontbuffer_bits) +		goto out; +  	fbc->busy_bits &= ~frontbuffer_bits;  	if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE)  		goto out; -	if (!fbc->busy_bits && fbc->state.plane && -	    (frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) { -		if (fbc->active) -			intel_fbc_nuke(fbc); -		else if (!fbc->flip_pending) -			__intel_fbc_post_update(fbc); -	} +	if (fbc->busy_bits || fbc->flip_pending) +		goto out; + +	if (fbc->active) +		intel_fbc_nuke(fbc); +	else +		intel_fbc_activate(fbc);  out:  	mutex_unlock(&fbc->lock); @@ -1445,6 +1470,7 @@ static void __intel_fbc_enable(struct intel_atomic_state *state,  	intel_fbc_update_state(state, crtc, plane); +	intel_fbc_program_workarounds(fbc);  	intel_fbc_program_cfb(fbc);  } @@ -1500,25 +1526,6 @@ void intel_fbc_update(struct intel_atomic_state *state,  	}  } -/** - * intel_fbc_global_disable - globally disable FBC - * @i915: i915 device instance - * - * This function disables FBC regardless of which CRTC is associated with it. - */ -void intel_fbc_global_disable(struct drm_i915_private *i915) -{ -	struct intel_fbc *fbc; -	enum intel_fbc_id fbc_id; - -	for_each_intel_fbc(i915, fbc, fbc_id) { -		mutex_lock(&fbc->lock); -		if (fbc->state.plane) -			__intel_fbc_disable(fbc); -		mutex_unlock(&fbc->lock); -	} -} -  static void intel_fbc_underrun_work_fn(struct work_struct *work)  {  	struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work); @@ -1640,7 +1647,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *i915)  static bool need_fbc_vtd_wa(struct drm_i915_private *i915)  {  	/* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ -	if (intel_vtd_active(i915) && +	if (i915_vtd_active(i915) &&  	    (IS_SKYLAKE(i915) || IS_BROXTON(i915))) {  		drm_info(&i915->drm,  			 "Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n"); @@ -1652,11 +1659,7 @@ static bool need_fbc_vtd_wa(struct drm_i915_private *i915)  void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane)  { -	if (!fbc) -		return; -  	plane->fbc = fbc; -	fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;  }  static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915, @@ -1709,22 +1712,26 @@ void intel_fbc_init(struct drm_i915_private *i915)  	drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n",  		    i915->params.enable_fbc); -	for_each_fbc_id(i915, fbc_id) { -		struct intel_fbc *fbc; +	for_each_fbc_id(i915, fbc_id) +		i915->fbc[fbc_id] = intel_fbc_create(i915, fbc_id); +} -		fbc = intel_fbc_create(i915, fbc_id); -		if (!fbc) -			continue; +/** + * intel_fbc_sanitize - Sanitize FBC + * @i915: the i915 device + * + * Make sure FBC is initially disabled since we have no + * idea eg. into which parts of stolen it might be scribbling + * into. + */ +void intel_fbc_sanitize(struct drm_i915_private *i915) +{ +	struct intel_fbc *fbc; +	enum intel_fbc_id fbc_id; -		/* -		 * We still don't have any sort of hardware state readout -		 * for FBC, so deactivate it in case the BIOS activated it -		 * to make sure software matches the hardware state. -		 */ +	for_each_intel_fbc(i915, fbc, fbc_id) {  		if (intel_fbc_hw_is_active(fbc))  			intel_fbc_hw_deactivate(fbc); - -		i915->fbc[fbc->id] = fbc;  	}  } @@ -1743,7 +1750,7 @@ static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)  	if (fbc->active) {  		seq_puts(m, "FBC enabled\n");  		seq_printf(m, "Compressing: %s\n", -			   yesno(intel_fbc_is_compressing(fbc))); +			   str_yes_no(intel_fbc_is_compressing(fbc)));  	} else {  		seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason);  	}  |