Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc41c154 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter
Browse files

drm/i915: Add support for variable cursor size on 845/865



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: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 8ac54669
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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)
+88 −23
Original line number Diff line number Diff line
@@ -8047,30 +8047,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) {
		unsigned int width = intel_crtc->cursor_width;
		unsigned int height = intel_crtc->cursor_height;
		unsigned int stride = roundup_pow_of_two(width) * 4;

	if (base != intel_crtc->cursor_base) {
		/* On these chipsets we can only modify the base whilst
		 * the cursor is disabled.
		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.
		 */
		if (intel_crtc->cursor_cntl) {
		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;
@@ -8169,6 +8194,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
 *
@@ -8183,7 +8245,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;

@@ -8197,14 +8259,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;
@@ -11797,6 +11858,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);
@@ -12585,7 +12647,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 {
+1 −0
Original line number Diff line number Diff line
@@ -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;