[Intel-gfx] [PATCH v4 4/4] drm/i915: Add support for variable cursor size on 845/865

Daniel Vetter daniel at ffwll.ch
Wed Aug 13 13:34:44 CEST 2014


On Wed, Aug 13, 2014 at 11:57:05AM +0300, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> 845/865 support different cursor sizes as well, albeit a bit differently
> than later platforms. Add the necessary code to make them work.
> 
> Untested due to lack of hardware.
> 
> v2: Warn but accept invalid stride (Chris)
>     Rewrite the cursor size checks for other platforms (Chris)
> v3: More polish and magic to the cursor size checks (Chris)
> v4: Moar polish and a comment (Chris)
> 
> Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

All merged to dinq, thanks.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_reg.h      |   3 +-
>  drivers/gpu/drm/i915/intel_display.c | 111 +++++++++++++++++++++++++++--------
>  drivers/gpu/drm/i915/intel_drv.h     |   1 +
>  3 files changed, 91 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index f79c20d..203062e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4128,7 +4128,8 @@ enum punit_power_well {
>  /* Old style CUR*CNTR flags (desktop 8xx) */
>  #define   CURSOR_ENABLE		0x80000000
>  #define   CURSOR_GAMMA_ENABLE	0x40000000
> -#define   CURSOR_STRIDE_MASK	0x30000000
> +#define   CURSOR_STRIDE_SHIFT	28
> +#define   CURSOR_STRIDE(x)	((ffs(x)-9) << CURSOR_STRIDE_SHIFT) /* 256,512,1k,2k */
>  #define   CURSOR_PIPE_CSC_ENABLE (1<<24)
>  #define   CURSOR_FORMAT_SHIFT	24
>  #define   CURSOR_FORMAT_MASK	(0x07 << CURSOR_FORMAT_SHIFT)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index a1cf052..0cefd15 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -8005,30 +8005,55 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	uint32_t cntl;
> +	uint32_t cntl = 0, size = 0;
>  
> -	if (base != intel_crtc->cursor_base) {
> -		/* On these chipsets we can only modify the base whilst
> -		 * the cursor is disabled.
> -		 */
> -		if (intel_crtc->cursor_cntl) {
> -			I915_WRITE(_CURACNTR, 0);
> -			POSTING_READ(_CURACNTR);
> -			intel_crtc->cursor_cntl = 0;
> +	if (base) {
> +		unsigned int width = intel_crtc->cursor_width;
> +		unsigned int height = intel_crtc->cursor_height;
> +		unsigned int stride = roundup_pow_of_two(width) * 4;
> +
> +		switch (stride) {
> +		default:
> +			WARN_ONCE(1, "Invalid cursor width/stride, width=%u, stride=%u\n",
> +				  width, stride);
> +			stride = 256;
> +			/* fallthrough */
> +		case 256:
> +		case 512:
> +		case 1024:
> +		case 2048:
> +			break;
>  		}
>  
> +		cntl |= CURSOR_ENABLE |
> +			CURSOR_GAMMA_ENABLE |
> +			CURSOR_FORMAT_ARGB |
> +			CURSOR_STRIDE(stride);
> +
> +		size = (height << 12) | width;
> +	}
> +
> +	if (intel_crtc->cursor_cntl != 0 &&
> +	    (intel_crtc->cursor_base != base ||
> +	     intel_crtc->cursor_size != size ||
> +	     intel_crtc->cursor_cntl != cntl)) {
> +		/* On these chipsets we can only modify the base/size/stride
> +		 * whilst the cursor is disabled.
> +		 */
> +		I915_WRITE(_CURACNTR, 0);
> +		POSTING_READ(_CURACNTR);
> +		intel_crtc->cursor_cntl = 0;
> +	}
> +
> +	if (intel_crtc->cursor_base != base)
>  		I915_WRITE(_CURABASE, base);
> -		POSTING_READ(_CURABASE);
> +
> +	if (intel_crtc->cursor_size != size) {
> +		I915_WRITE(CURSIZE, size);
> +		intel_crtc->cursor_size = size;
>  	}
>  
> -	/* XXX width must be 64, stride 256 => 0x00 << 28 */
> -	cntl = 0;
> -	if (base)
> -		cntl = (CURSOR_ENABLE |
> -			CURSOR_GAMMA_ENABLE |
> -			CURSOR_FORMAT_ARGB);
>  	if (intel_crtc->cursor_cntl != cntl) {
> -		I915_WRITE(CURSIZE, (64 << 12) | 64);
>  		I915_WRITE(_CURACNTR, cntl);
>  		POSTING_READ(_CURACNTR);
>  		intel_crtc->cursor_cntl = cntl;
> @@ -8127,6 +8152,43 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
>  	intel_crtc->cursor_base = base;
>  }
>  
> +static bool cursor_size_ok(struct drm_device *dev,
> +			   uint32_t width, uint32_t height)
> +{
> +	if (width == 0 || height == 0)
> +		return false;
> +
> +	/*
> +	 * 845g/865g are special in that they are only limited by
> +	 * the width of their cursors, the height is arbitrary up to
> +	 * the precision of the register. Everything else requires
> +	 * square cursors, limited to a few power-of-two sizes.
> +	 */
> +	if (IS_845G(dev) || IS_I865G(dev)) {
> +		if ((width & 63) != 0)
> +			return false;
> +
> +		if (width > (IS_845G(dev) ? 64 : 512))
> +			return false;
> +
> +		if (height > 1023)
> +			return false;
> +	} else {
> +		switch (width | height) {
> +		case 256:
> +		case 128:
> +			if (IS_GEN2(dev))
> +				return false;
> +		case 64:
> +			break;
> +		default:
> +			return false;
> +		}
> +	}
> +
> +	return true;
> +}
> +
>  /*
>   * intel_crtc_cursor_set_obj - Set cursor to specified GEM object
>   *
> @@ -8141,7 +8203,7 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
>  	struct drm_device *dev = crtc->dev;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	enum pipe pipe = intel_crtc->pipe;
> -	unsigned old_width;
> +	unsigned old_width, stride;
>  	uint32_t addr;
>  	int ret;
>  
> @@ -8155,14 +8217,13 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
>  	}
>  
>  	/* Check for which cursor types we support */
> -	if (!((width == 64 && height == 64) ||
> -			(width == 128 && height == 128 && !IS_GEN2(dev)) ||
> -			(width == 256 && height == 256 && !IS_GEN2(dev)))) {
> +	if (!cursor_size_ok(dev, width, height)) {
>  		DRM_DEBUG("Cursor dimension not supported\n");
>  		return -EINVAL;
>  	}
>  
> -	if (obj->base.size < width * height * 4) {
> +	stride = roundup_pow_of_two(width) * 4;
> +	if (obj->base.size < stride * height) {
>  		DRM_DEBUG_KMS("buffer is too small\n");
>  		ret = -ENOMEM;
>  		goto fail;
> @@ -11755,6 +11816,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
>  
>  	intel_crtc->cursor_base = ~0;
>  	intel_crtc->cursor_cntl = ~0;
> +	intel_crtc->cursor_size = ~0;
>  
>  	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
>  	       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
> @@ -12543,7 +12605,10 @@ void intel_modeset_init(struct drm_device *dev)
>  		dev->mode_config.max_height = 8192;
>  	}
>  
> -	if (IS_GEN2(dev)) {
> +	if (IS_845G(dev) || IS_I865G(dev)) {
> +		dev->mode_config.cursor_width = IS_845G(dev) ? 64 : 512;
> +		dev->mode_config.cursor_height = 1023;
> +	} else if (IS_GEN2(dev)) {
>  		dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH;
>  		dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT;
>  	} else {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1b3d1d7..3cde050 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -405,6 +405,7 @@ struct intel_crtc {
>  	uint32_t cursor_addr;
>  	int16_t cursor_width, cursor_height;
>  	uint32_t cursor_cntl;
> +	uint32_t cursor_size;
>  	uint32_t cursor_base;
>  
>  	struct intel_plane_config plane_config;
> -- 
> 1.8.5.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch



More information about the Intel-gfx mailing list