diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_fb.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_fb.c | 187 | 
1 files changed, 80 insertions, 107 deletions
| diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 19b35ece31f1..0c0144eaa8fa 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -4,7 +4,6 @@   */  #include <drm/drm_blend.h> -#include <drm/drm_framebuffer.h>  #include <drm/drm_modeset_helper.h>  #include <linux/dma-fence.h> @@ -15,6 +14,7 @@  #include "intel_display_types.h"  #include "intel_dpt.h"  #include "intel_fb.h" +#include "intel_fb_bo.h"  #include "intel_frontbuffer.h"  #define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a)) @@ -301,6 +301,33 @@ lookup_format_info(const struct drm_format_info formats[],  	return NULL;  } +unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) +{ +	const struct intel_modifier_desc *md; +	u8 tiling_caps; + +	md = lookup_modifier_or_null(fb_modifier); +	if (!md) +		return I915_TILING_NONE; + +	tiling_caps = lookup_modifier_or_null(fb_modifier)->plane_caps & +			 INTEL_PLANE_CAP_TILING_MASK; + +	switch (tiling_caps) { +	case INTEL_PLANE_CAP_TILING_Y: +		return I915_TILING_Y; +	case INTEL_PLANE_CAP_TILING_X: +		return I915_TILING_X; +	case INTEL_PLANE_CAP_TILING_4: +	case INTEL_PLANE_CAP_TILING_Yf: +	case INTEL_PLANE_CAP_TILING_NONE: +		return I915_TILING_NONE; +	default: +		MISSING_CASE(tiling_caps); +		return I915_TILING_NONE; +	} +} +  /**   * intel_fb_get_format_info: Get a modifier specific format information   * @cmd: FB add command structure @@ -737,26 +764,6 @@ intel_fb_align_height(const struct drm_framebuffer *fb,  	return ALIGN(height, tile_height);  } -static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) -{ -	u8 tiling_caps = lookup_modifier(fb_modifier)->plane_caps & -			 INTEL_PLANE_CAP_TILING_MASK; - -	switch (tiling_caps) { -	case INTEL_PLANE_CAP_TILING_Y: -		return I915_TILING_Y; -	case INTEL_PLANE_CAP_TILING_X: -		return I915_TILING_X; -	case INTEL_PLANE_CAP_TILING_4: -	case INTEL_PLANE_CAP_TILING_Yf: -	case INTEL_PLANE_CAP_TILING_NONE: -		return I915_TILING_NONE; -	default: -		MISSING_CASE(tiling_caps); -		return I915_TILING_NONE; -	} -} -  bool intel_fb_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier)  {  	return HAS_DPT(i915) && modifier != DRM_FORMAT_MOD_LINEAR; @@ -764,7 +771,7 @@ bool intel_fb_modifier_uses_dpt(struct drm_i915_private *i915, u64 modifier)  bool intel_fb_uses_dpt(const struct drm_framebuffer *fb)  { -	return fb && to_i915(fb->dev)->params.enable_dpt && +	return to_i915(fb->dev)->display.params.enable_dpt &&  		intel_fb_modifier_uses_dpt(to_i915(fb->dev), fb->modifier);  } @@ -1374,7 +1381,8 @@ plane_view_scanout_stride(const struct intel_framebuffer *fb, int color_plane,  	struct drm_i915_private *i915 = to_i915(fb->base.dev);  	unsigned int stride_tiles; -	if (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) +	if ((IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14) && +	    src_stride_tiles < dst_stride_tiles)  		stride_tiles = src_stride_tiles;  	else  		stride_tiles = dst_stride_tiles; @@ -1501,8 +1509,20 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p  			size += remap_info->size;  		} else { -			unsigned int dst_stride = plane_view_dst_stride_tiles(fb, color_plane, -									      remap_info->width); +			unsigned int dst_stride; + +			/* +			 * The hardware automagically calculates the CCS AUX surface +			 * stride from the main surface stride so can't really remap a +			 * smaller subset (unless we'd remap in whole AUX page units). +			 */ +			if (intel_fb_needs_pot_stride_remap(fb) && +			    intel_fb_is_ccs_modifier(fb->base.modifier)) +				dst_stride = remap_info->src_stride; +			else +				dst_stride = remap_info->width; + +			dst_stride = plane_view_dst_stride_tiles(fb, color_plane, dst_stride);  			assign_chk_ovf(i915, remap_info->dst_stride, dst_stride);  			color_plane_info->mapping_stride = dst_stride * @@ -1657,10 +1677,10 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *  		max_size = max(max_size, offset + size);  	} -	if (mul_u32_u32(max_size, tile_size) > obj->base.size) { +	if (mul_u32_u32(max_size, tile_size) > intel_bo_to_drm_bo(obj)->size) {  		drm_dbg_kms(&i915->drm,  			    "fb too big for bo (need %llu bytes, have %zu bytes)\n", -			    mul_u32_u32(max_size, tile_size), obj->base.size); +			    mul_u32_u32(max_size, tile_size), intel_bo_to_drm_bo(obj)->size);  		return -EINVAL;  	} @@ -1881,6 +1901,8 @@ static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)  	intel_frontbuffer_put(intel_fb->frontbuffer); +	intel_fb_bo_framebuffer_fini(intel_fb_obj(fb)); +  	kfree(intel_fb);  } @@ -1889,7 +1911,7 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,  						unsigned int *handle)  {  	struct drm_i915_gem_object *obj = intel_fb_obj(fb); -	struct drm_i915_private *i915 = to_i915(obj->base.dev); +	struct drm_i915_private *i915 = to_i915(intel_bo_to_drm_bo(obj)->dev);  	if (i915_gem_object_is_userptr(obj)) {  		drm_dbg(&i915->drm, @@ -1897,7 +1919,7 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,  		return -EINVAL;  	} -	return drm_gem_handle_create(file, &obj->base, handle); +	return drm_gem_handle_create(file, intel_bo_to_drm_bo(obj), handle);  }  struct frontbuffer_fence_cb { @@ -1930,10 +1952,10 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,  	if (!atomic_read(&front->bits))  		return 0; -	if (dma_resv_test_signaled(obj->base.resv, dma_resv_usage_rw(false))) +	if (dma_resv_test_signaled(intel_bo_to_drm_bo(obj)->resv, dma_resv_usage_rw(false)))  		goto flush; -	ret = dma_resv_get_singleton(obj->base.resv, dma_resv_usage_rw(false), +	ret = dma_resv_get_singleton(intel_bo_to_drm_bo(obj)->resv, dma_resv_usage_rw(false),  				     &fence);  	if (ret || !fence)  		goto flush; @@ -1975,61 +1997,30 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  			   struct drm_i915_gem_object *obj,  			   struct drm_mode_fb_cmd2 *mode_cmd)  { -	struct drm_i915_private *dev_priv = to_i915(obj->base.dev); +	struct drm_i915_private *dev_priv = to_i915(intel_bo_to_drm_bo(obj)->dev);  	struct drm_framebuffer *fb = &intel_fb->base;  	u32 max_stride; -	unsigned int tiling, stride;  	int ret = -EINVAL;  	int i; -	intel_fb->frontbuffer = intel_frontbuffer_get(obj); -	if (!intel_fb->frontbuffer) -		return -ENOMEM; - -	i915_gem_object_lock(obj, NULL); -	tiling = i915_gem_object_get_tiling(obj); -	stride = i915_gem_object_get_stride(obj); -	i915_gem_object_unlock(obj); +	ret = intel_fb_bo_framebuffer_init(intel_fb, obj, mode_cmd); +	if (ret) +		return ret; -	if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) { -		/* -		 * If there's a fence, enforce that -		 * the fb modifier and tiling mode match. -		 */ -		if (tiling != I915_TILING_NONE && -		    tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) { -			drm_dbg_kms(&dev_priv->drm, -				    "tiling_mode doesn't match fb modifier\n"); -			goto err; -		} -	} else { -		if (tiling == I915_TILING_X) { -			mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED; -		} else if (tiling == I915_TILING_Y) { -			drm_dbg_kms(&dev_priv->drm, -				    "No Y tiling for legacy addfb\n"); -			goto err; -		} +	intel_fb->frontbuffer = intel_frontbuffer_get(obj); +	if (!intel_fb->frontbuffer) { +		ret = -ENOMEM; +		goto err;  	} +	ret = -EINVAL;  	if (!drm_any_plane_has_format(&dev_priv->drm,  				      mode_cmd->pixel_format,  				      mode_cmd->modifier[0])) {  		drm_dbg_kms(&dev_priv->drm,  			    "unsupported pixel format %p4cc / modifier 0x%llx\n",  			    &mode_cmd->pixel_format, mode_cmd->modifier[0]); -		goto err; -	} - -	/* -	 * gen2/3 display engine uses the fence if present, -	 * so the tiling mode must match the fb modifier exactly. -	 */ -	if (DISPLAY_VER(dev_priv) < 4 && -	    tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) { -		drm_dbg_kms(&dev_priv->drm, -			    "tiling_mode must match fb modifier exactly on gen2/3\n"); -		goto err; +		goto err_frontbuffer_put;  	}  	max_stride = intel_fb_max_stride(dev_priv, mode_cmd->pixel_format, @@ -2040,18 +2031,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  			    mode_cmd->modifier[0] != DRM_FORMAT_MOD_LINEAR ?  			    "tiled" : "linear",  			    mode_cmd->pitches[0], max_stride); -		goto err; -	} - -	/* -	 * If there's a fence, enforce that -	 * the fb pitch and fence stride match. -	 */ -	if (tiling != I915_TILING_NONE && mode_cmd->pitches[0] != stride) { -		drm_dbg_kms(&dev_priv->drm, -			    "pitch (%d) must match tiling stride (%d)\n", -			    mode_cmd->pitches[0], stride); -		goto err; +		goto err_frontbuffer_put;  	}  	/* FIXME need to adjust LINOFF/TILEOFF accordingly. */ @@ -2059,7 +2039,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  		drm_dbg_kms(&dev_priv->drm,  			    "plane 0 offset (0x%08x) must be 0\n",  			    mode_cmd->offsets[0]); -		goto err; +		goto err_frontbuffer_put;  	}  	drm_helper_mode_fill_fb_struct(&dev_priv->drm, fb, mode_cmd); @@ -2070,7 +2050,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  		if (mode_cmd->handles[i] != mode_cmd->handles[0]) {  			drm_dbg_kms(&dev_priv->drm, "bad plane %d handle\n",  				    i); -			goto err; +			goto err_frontbuffer_put;  		}  		stride_alignment = intel_fb_stride_alignment(fb, i); @@ -2078,7 +2058,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  			drm_dbg_kms(&dev_priv->drm,  				    "plane %d pitch (%d) must be at least %u byte aligned\n",  				    i, fb->pitches[i], stride_alignment); -			goto err; +			goto err_frontbuffer_put;  		}  		if (intel_fb_is_gen12_ccs_aux_plane(fb, i)) { @@ -2089,16 +2069,16 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  					    "ccs aux plane %d pitch (%d) must be %d\n",  					    i,  					    fb->pitches[i], ccs_aux_stride); -				goto err; +				goto err_frontbuffer_put;  			}  		} -		fb->obj[i] = &obj->base; +		fb->obj[i] = intel_bo_to_drm_bo(obj);  	}  	ret = intel_fill_fb_info(dev_priv, intel_fb);  	if (ret) -		goto err; +		goto err_frontbuffer_put;  	if (intel_fb_uses_dpt(fb)) {  		struct i915_address_space *vm; @@ -2107,7 +2087,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  		if (IS_ERR(vm)) {  			drm_dbg_kms(&dev_priv->drm, "failed to create DPT\n");  			ret = PTR_ERR(vm); -			goto err; +			goto err_frontbuffer_put;  		}  		intel_fb->dpt_vm = vm; @@ -2124,8 +2104,10 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  err_free_dpt:  	if (intel_fb_uses_dpt(fb))  		intel_dpt_destroy(intel_fb->dpt_vm); -err: +err_frontbuffer_put:  	intel_frontbuffer_put(intel_fb->frontbuffer); +err: +	intel_fb_bo_framebuffer_fini(obj);  	return ret;  } @@ -2137,23 +2119,14 @@ intel_user_framebuffer_create(struct drm_device *dev,  	struct drm_framebuffer *fb;  	struct drm_i915_gem_object *obj;  	struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd; -	struct drm_i915_private *i915; - -	obj = i915_gem_object_lookup(filp, mode_cmd.handles[0]); -	if (!obj) -		return ERR_PTR(-ENOENT); - -	/* object is backed with LMEM for discrete */ -	i915 = to_i915(obj->base.dev); -	if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM_0)) { -		/* object is "remote", not in local memory */ -		i915_gem_object_put(obj); -		drm_dbg_kms(&i915->drm, "framebuffer must reside in local memory\n"); -		return ERR_PTR(-EREMOTE); -	} +	struct drm_i915_private *i915 = to_i915(dev); + +	obj = intel_fb_bo_lookup_valid_bo(i915, filp, &mode_cmd); +	if (IS_ERR(obj)) +		return ERR_CAST(obj);  	fb = intel_framebuffer_create(obj, &mode_cmd); -	i915_gem_object_put(obj); +	drm_gem_object_put(intel_bo_to_drm_bo(obj));  	return fb;  } | 
