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

Commit 66a2d927 authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915: Make intel_adjust_tile_offset() work for linear buffers



To make life less surprising we can make intel_adjust_tile_offset()
deal with linear buffers as well. Currently it doesn't seem like there's
a real need for this since only X tiling and NV12 (which would always
be tiled currently) should need it. But I've used it for some debug
hacks already so seems like a reasonable thing to have.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarSivakumar Thulasimani <sivakumar.thulasimani@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470821001-25272-10-git-send-email-ville.syrjala@linux.intel.com
parent b9b24038
Loading
Loading
Loading
Loading
+57 −16
Original line number Diff line number Diff line
@@ -2316,13 +2316,10 @@ void intel_add_fb_offsets(int *x, int *y,
}

/*
 * Adjust the tile offset by moving the difference into
 * the x/y offsets.
 *
 * Input tile dimensions and pitch must already be
 * rotated to match x and y, and in pixel units.
 */
static u32 intel_adjust_tile_offset(int *x, int *y,
static u32 _intel_adjust_tile_offset(int *x, int *y,
				     unsigned int tile_width,
				     unsigned int tile_height,
				     unsigned int tile_size,
@@ -2349,6 +2346,50 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
	return new_offset;
}

/*
 * Adjust the tile offset by moving the difference into
 * the x/y offsets.
 */
static u32 intel_adjust_tile_offset(int *x, int *y,
				    const struct intel_plane_state *state, int plane,
				    u32 old_offset, u32 new_offset)
{
	const struct drm_i915_private *dev_priv = to_i915(state->base.plane->dev);
	const struct drm_framebuffer *fb = state->base.fb;
	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
	unsigned int rotation = state->base.rotation;
	unsigned int pitch = intel_fb_pitch(fb, plane, rotation);

	WARN_ON(new_offset > old_offset);

	if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
		unsigned int tile_size, tile_width, tile_height;
		unsigned int pitch_tiles;

		tile_size = intel_tile_size(dev_priv);
		intel_tile_dims(dev_priv, &tile_width, &tile_height,
				fb->modifier[plane], cpp);

		if (intel_rotation_90_or_270(rotation)) {
			pitch_tiles = pitch / tile_height;
			swap(tile_width, tile_height);
		} else {
			pitch_tiles = pitch / (tile_width * cpp);
		}

		_intel_adjust_tile_offset(x, y, tile_width, tile_height,
					  tile_size, pitch_tiles,
					  old_offset, new_offset);
	} else {
		old_offset += *y * pitch + *x * cpp;

		*y = (old_offset - new_offset) / pitch;
		*x = ((old_offset - new_offset) - *y * pitch) / cpp;
	}

	return new_offset;
}

/*
 * Computes the linear offset to the base tile and adjusts
 * x, y. bytes per pixel is assumed to be a power-of-two.
@@ -2401,7 +2442,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
		offset = (tile_rows * pitch_tiles + tiles) * tile_size;
		offset_aligned = offset & ~alignment;

		intel_adjust_tile_offset(x, y, tile_width, tile_height,
		_intel_adjust_tile_offset(x, y, tile_width, tile_height,
					  tile_size, pitch_tiles,
					  offset, offset_aligned);
	} else {
@@ -2550,7 +2591,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
			 * We only keep the x/y offsets, so push all of the
			 * gtt offset into the x/y offsets.
			 */
			intel_adjust_tile_offset(&x, &y, tile_size,
			_intel_adjust_tile_offset(&x, &y, tile_size,
						  tile_width, tile_height, pitch_tiles,
						  gtt_offset_rotated * tile_size, 0);