diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_sprite.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_sprite.c | 235 | 
1 files changed, 213 insertions, 22 deletions
| diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 63040cb0d4e1..019a2d6d807a 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -47,6 +47,7 @@  #include "intel_frontbuffer.h"  #include "intel_pm.h"  #include "intel_psr.h" +#include "intel_dsi.h"  #include "intel_sprite.h"  int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, @@ -93,6 +94,9 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)  	DEFINE_WAIT(wait);  	u32 psr_status; +	if (new_crtc_state->uapi.async_flip) +		return; +  	vblank_start = adjusted_mode->crtc_vblank_start;  	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)  		vblank_start = DIV_ROUND_UP(vblank_start, 2); @@ -200,8 +204,19 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)  	ktime_t end_vbl_time = ktime_get();  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); +	if (new_crtc_state->uapi.async_flip) +		return; +  	trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end); +	/* +	 * Incase of mipi dsi command mode, we need to set frame update +	 * request for every commit. +	 */ +	if (INTEL_GEN(dev_priv) >= 11 && +	    intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI)) +		icl_dsi_frame_update(new_crtc_state); +  	/* We're still in the vblank-evade critical section, this can't race.  	 * Would be slightly nice to just grab the vblank count and arm the  	 * event outside of the critical section - the spinlock might spin for a @@ -393,6 +408,134 @@ static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,  	return DIV_ROUND_UP(pixel_rate * num, den);  } +static int skl_plane_max_width(const struct drm_framebuffer *fb, +			       int color_plane, +			       unsigned int rotation) +{ +	int cpp = fb->format->cpp[color_plane]; + +	switch (fb->modifier) { +	case DRM_FORMAT_MOD_LINEAR: +	case I915_FORMAT_MOD_X_TILED: +		/* +		 * Validated limit is 4k, but has 5k should +		 * work apart from the following features: +		 * - Ytile (already limited to 4k) +		 * - FP16 (already limited to 4k) +		 * - render compression (already limited to 4k) +		 * - KVMR sprite and cursor (don't care) +		 * - horizontal panning (TODO verify this) +		 * - pipe and plane scaling (TODO verify this) +		 */ +		if (cpp == 8) +			return 4096; +		else +			return 5120; +	case I915_FORMAT_MOD_Y_TILED_CCS: +	case I915_FORMAT_MOD_Yf_TILED_CCS: +	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: +		/* FIXME AUX plane? */ +	case I915_FORMAT_MOD_Y_TILED: +	case I915_FORMAT_MOD_Yf_TILED: +		if (cpp == 8) +			return 2048; +		else +			return 4096; +	default: +		MISSING_CASE(fb->modifier); +		return 2048; +	} +} + +static int glk_plane_max_width(const struct drm_framebuffer *fb, +			       int color_plane, +			       unsigned int rotation) +{ +	int cpp = fb->format->cpp[color_plane]; + +	switch (fb->modifier) { +	case DRM_FORMAT_MOD_LINEAR: +	case I915_FORMAT_MOD_X_TILED: +		if (cpp == 8) +			return 4096; +		else +			return 5120; +	case I915_FORMAT_MOD_Y_TILED_CCS: +	case I915_FORMAT_MOD_Yf_TILED_CCS: +		/* FIXME AUX plane? */ +	case I915_FORMAT_MOD_Y_TILED: +	case I915_FORMAT_MOD_Yf_TILED: +		if (cpp == 8) +			return 2048; +		else +			return 5120; +	default: +		MISSING_CASE(fb->modifier); +		return 2048; +	} +} + +static int icl_plane_min_width(const struct drm_framebuffer *fb, +			       int color_plane, +			       unsigned int rotation) +{ +	/* Wa_14011264657, Wa_14011050563: gen11+ */ +	switch (fb->format->format) { +	case DRM_FORMAT_C8: +		return 18; +	case DRM_FORMAT_RGB565: +		return 10; +	case DRM_FORMAT_XRGB8888: +	case DRM_FORMAT_XBGR8888: +	case DRM_FORMAT_ARGB8888: +	case DRM_FORMAT_ABGR8888: +	case DRM_FORMAT_XRGB2101010: +	case DRM_FORMAT_XBGR2101010: +	case DRM_FORMAT_ARGB2101010: +	case DRM_FORMAT_ABGR2101010: +	case DRM_FORMAT_XVYU2101010: +	case DRM_FORMAT_Y212: +	case DRM_FORMAT_Y216: +		return 6; +	case DRM_FORMAT_NV12: +		return 20; +	case DRM_FORMAT_P010: +	case DRM_FORMAT_P012: +	case DRM_FORMAT_P016: +		return 12; +	case DRM_FORMAT_XRGB16161616F: +	case DRM_FORMAT_XBGR16161616F: +	case DRM_FORMAT_ARGB16161616F: +	case DRM_FORMAT_ABGR16161616F: +	case DRM_FORMAT_XVYU12_16161616: +	case DRM_FORMAT_XVYU16161616: +		return 4; +	default: +		return 1; +	} +} + +static int icl_plane_max_width(const struct drm_framebuffer *fb, +			       int color_plane, +			       unsigned int rotation) +{ +	return 5120; +} + +static int skl_plane_max_height(const struct drm_framebuffer *fb, +				int color_plane, +				unsigned int rotation) +{ +	return 4096; +} + +static int icl_plane_max_height(const struct drm_framebuffer *fb, +				int color_plane, +				unsigned int rotation) +{ +	return 4320; +} +  static unsigned int  skl_plane_max_stride(struct intel_plane *plane,  		     u32 pixel_format, u64 modifier, @@ -429,6 +572,7 @@ skl_program_scaler(struct intel_plane *plane,  	u16 y_hphase, uv_rgb_hphase;  	u16 y_vphase, uv_rgb_vphase;  	int hscale, vscale; +	u32 ps_ctrl;  	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,  				      &plane_state->uapi.dst, @@ -455,8 +599,13 @@ skl_program_scaler(struct intel_plane *plane,  		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);  	} -	intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id), -			  PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode); +	ps_ctrl = skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0); +	ps_ctrl |= PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode; + +	skl_scaler_setup_filter(dev_priv, pipe, scaler_id, 0, +				plane_state->hw.scaling_filter); + +	intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);  	intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, scaler_id),  			  PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));  	intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id), @@ -604,6 +753,29 @@ icl_program_input_csc(struct intel_plane *plane,  }  static void +skl_plane_async_flip(struct intel_plane *plane, +		     const struct intel_crtc_state *crtc_state, +		     const struct intel_plane_state *plane_state) +{ +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev); +	unsigned long irqflags; +	enum plane_id plane_id = plane->id; +	enum pipe pipe = plane->pipe; +	u32 surf_addr = plane_state->color_plane[0].offset; +	u32 plane_ctl = plane_state->ctl; + +	plane_ctl |= skl_plane_ctl_crtc(crtc_state); + +	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + +	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); +	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), +			  intel_plane_ggtt_offset(plane_state) + surf_addr); + +	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void  skl_program_plane(struct intel_plane *plane,  		  const struct intel_crtc_state *crtc_state,  		  const struct intel_plane_state *plane_state, @@ -617,8 +789,6 @@ skl_program_plane(struct intel_plane *plane,  	u32 stride = skl_plane_stride(plane_state, color_plane);  	const struct drm_framebuffer *fb = plane_state->hw.fb;  	int aux_plane = intel_main_to_aux_plane(fb, color_plane); -	u32 aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr; -	u32 aux_stride = skl_plane_stride(plane_state, aux_plane);  	int crtc_x = plane_state->uapi.dst.x1;  	int crtc_y = plane_state->uapi.dst.y1;  	u32 x = plane_state->color_plane[color_plane].x; @@ -626,7 +796,7 @@ skl_program_plane(struct intel_plane *plane,  	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;  	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;  	u8 alpha = plane_state->hw.alpha >> 8; -	u32 plane_color_ctl = 0; +	u32 plane_color_ctl = 0, aux_dist = 0;  	unsigned long irqflags;  	u32 keymsk, keymax;  	u32 plane_ctl = plane_state->ctl; @@ -653,6 +823,13 @@ skl_program_plane(struct intel_plane *plane,  		crtc_y = 0;  	} +	if (aux_plane) { +		aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr; + +		if (INTEL_GEN(dev_priv) < 12) +			aux_dist |= skl_plane_stride(plane_state, aux_plane); +	} +  	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);  	intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride); @@ -661,8 +838,6 @@ skl_program_plane(struct intel_plane *plane,  	intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),  			  (src_h << 16) | src_w); -	if (INTEL_GEN(dev_priv) < 12) -		aux_dist |= aux_stride;  	intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);  	if (icl_is_hdr_plane(dev_priv, plane_id)) @@ -690,6 +865,9 @@ skl_program_plane(struct intel_plane *plane,  		intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),  				  (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x); +	if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) +		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); +  	/*  	 * The control register self-arms if the plane was previously  	 * disabled. Try to make the plane enable atomic by writing @@ -2009,10 +2187,8 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state,  		}  	} -	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, -						  &crtc_state->uapi, -						  min_scale, max_scale, -						  true, true); +	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, +						min_scale, max_scale, true);  	if (ret)  		return ret; @@ -2067,11 +2243,10 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,  	if (ret)  		return ret; -	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, -						  &crtc_state->uapi, -						  DRM_PLANE_HELPER_NO_SCALING, -						  DRM_PLANE_HELPER_NO_SCALING, -						  true, true); +	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, +						DRM_PLANE_HELPER_NO_SCALING, +						DRM_PLANE_HELPER_NO_SCALING, +						true);  	if (ret)  		return ret; @@ -2278,10 +2453,8 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state,  		max_scale = skl_plane_max_scale(dev_priv, fb);  	} -	ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, -						  &crtc_state->uapi, -						  min_scale, max_scale, -						  true, true); +	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, +						min_scale, max_scale, true);  	if (ret)  		return ret; @@ -2842,8 +3015,8 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane,  static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,  					enum plane_id plane_id)  { -	/* Wa_14010477008:tgl[a0..c0],rkl[all] */ -	if (IS_ROCKETLAKE(dev_priv) || +	/* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */ +	if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||  	    IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0))  		return false; @@ -3083,12 +3256,25 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,  		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;  	} +	if (INTEL_GEN(dev_priv) >= 11) { +		plane->min_width = icl_plane_min_width; +		plane->max_width = icl_plane_max_width; +		plane->max_height = icl_plane_max_height; +	} else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { +		plane->max_width = glk_plane_max_width; +		plane->max_height = skl_plane_max_height; +	} else { +		plane->max_width = skl_plane_max_width; +		plane->max_height = skl_plane_max_height; +	} +  	plane->max_stride = skl_plane_max_stride;  	plane->update_plane = skl_update_plane;  	plane->disable_plane = skl_disable_plane;  	plane->get_hw_state = skl_plane_get_hw_state;  	plane->check_plane = skl_plane_check;  	plane->min_cdclk = skl_plane_min_cdclk; +	plane->async_flip = skl_plane_async_flip;  	if (INTEL_GEN(dev_priv) >= 11)  		formats = icl_get_plane_formats(dev_priv, pipe, @@ -3160,6 +3346,11 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,  	if (INTEL_GEN(dev_priv) >= 12)  		drm_plane_enable_fb_damage_clips(&plane->base); +	if (INTEL_GEN(dev_priv) >= 10) +		drm_plane_create_scaling_filter_property(&plane->base, +						BIT(DRM_SCALING_FILTER_DEFAULT) | +						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); +  	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);  	return plane; | 
