All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic
@ 2015-10-14 16:28 ville.syrjala
  2015-10-14 16:28 ` [PATCH 01/22] drm: Add drm_format_plane_width() and drm_format_plane_height() ville.syrjala
                   ` (22 more replies)
  0 siblings, 23 replies; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

So while reviewing the NV12 stuff it became clear to me no one
had really given fb->offsets[] handling any serious thought.
So this patch series aims to fix that. We now treat fb->offsets[]
as a linear offset always. One clear benefit over treating it as
a linear offset as opposed to a raw byte offset is that we don't
have to think about the layout of bytes within the tile at all.

The series also generalizes the page rotation to be format agnostic,
the caller just specifies the desired geometry in pages for each
plane, and the rotation code builds up the sg. The intel_rotation_info
then just contains the minimal amount of information needed to
do the page rotation.

SKL+ also gets changed to use the compute_page_offset stuff so that
the plane SURF register will contain the closes (properly aligned)
page boundary, and the x/y offsets deal with whatever is left over.
The plane code for the other platforms also gets simpler in the end
I think. Also the 90/270 rotation handling becomes rather trivial
for the plane code.

I should still write some decent tests to exercise fb->offsets[].

Series available here:
git://github.com/vsyrjala/linux.git fb_offsets

Ville Syrjälä (22):
  drm: Add drm_format_plane_width() and drm_format_plane_height()
  drm/i915: Pass modifier instead of tiling_mode to
    gen4_compute_page_offset()
  drm/i915: Factor out intel_tile_width()
  drm/i915: Redo intel_tile_height() as intel_tile_size() /
    intel_tile_width()
  drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size
  drm/i915: Use intel_tile_{size,width,height}() in
    intel_gen4_compute_page_offset()
  drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/
  drm/i915: Pass 90/270 vs. 0/180 rotation info for
    intel_gen4_compute_page_offset()
  drm/i915: Refactor intel_surf_alignment()
  drm/i915: Support for extra alignment for tiled surfaces
  drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  drm/i915: Set i915_ggtt_view_normal type explicitly
  drm/i915: Move the partial and rotated view data into the same union
  drm/i915: Don't treat differently sized rotated views as equal
  drm/i915: Pass the dma_addr_t array as const to rotate_pages()
  drm/i915: Pass stride to rotate_pages()
  drm/i915: Pass rotation_info to intel_rotate_fb_obj_pages()
  drm/i915: Make sure fb offset is (macro)pixel aligned
  drm/i915: Don't leak framebuffer_references if drm_framebuffer_init()
    fails
  drm/i915: Pass drm_frambuffer to intel_compute_page_offset()
  drm/i915: Rewrite fb rotation GTT handling
  drm/i915: Don't pass pitch to intel_compute_page_offset()

 drivers/gpu/drm/i915/i915_gem.c      |  10 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c  |  88 ++--
 drivers/gpu/drm/i915/i915_gem_gtt.h  |  27 +-
 drivers/gpu/drm/i915/intel_display.c | 792 +++++++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_drv.h     |  46 +-
 drivers/gpu/drm/i915/intel_fbdev.c   |   2 +-
 drivers/gpu/drm/i915/intel_sprite.c  | 128 +++---
 include/drm/drm_crtc.h               |  12 +
 8 files changed, 681 insertions(+), 424 deletions(-)

-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH 01/22] drm: Add drm_format_plane_width() and drm_format_plane_height()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
@ 2015-10-14 16:28 ` ville.syrjala
  2015-10-21  9:53   ` Daniel Vetter
  2015-10-14 16:28 ` [PATCH 02/22] drm/i915: Pass modifier instead of tiling_mode to gen4_compute_page_offset() ville.syrjala
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a few helpers to get the dimensions of the chroma plane(s).

Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_crtc.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 33ddedd..317baf9 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1497,6 +1497,18 @@ extern int drm_format_num_planes(uint32_t format);
 extern int drm_format_plane_cpp(uint32_t format, int plane);
 extern int drm_format_horz_chroma_subsampling(uint32_t format);
 extern int drm_format_vert_chroma_subsampling(uint32_t format);
+static inline int drm_format_plane_width(int width, uint32_t format, int plane)
+{
+	if (plane == 0)
+		return width;
+	return width / drm_format_horz_chroma_subsampling(format);
+}
+static inline int drm_format_plane_height(int height, uint32_t format, int plane)
+{
+	if (plane == 0)
+		return height;
+	return height / drm_format_vert_chroma_subsampling(format);
+}
 extern const char *drm_get_format_name(uint32_t format);
 extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
 							      unsigned int supported_rotations);
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 02/22] drm/i915: Pass modifier instead of tiling_mode to gen4_compute_page_offset()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
  2015-10-14 16:28 ` [PATCH 01/22] drm: Add drm_format_plane_width() and drm_format_plane_height() ville.syrjala
@ 2015-10-14 16:28 ` ville.syrjala
  2015-10-21  9:54   ` Daniel Vetter
  2015-10-14 16:28 ` [PATCH 03/22] drm/i915: Factor out intel_tile_width() ville.syrjala
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

In preparation for handling more than X tiling, pass the fb modifier to
gen4_compute_page_offset() instead of the obj->tiling_mode.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 8 ++++----
 drivers/gpu/drm/i915/intel_drv.h     | 4 ++--
 drivers/gpu/drm/i915/intel_sprite.c  | 6 +++---
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c28fb6a..6add8d1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2447,11 +2447,11 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
  * is assumed to be a power-of-two. */
 unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
 					     int *x, int *y,
-					     unsigned int tiling_mode,
+					     uint64_t fb_modifier,
 					     unsigned int cpp,
 					     unsigned int pitch)
 {
-	if (tiling_mode != I915_TILING_NONE) {
+	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_rows, tiles;
 
 		tile_rows = *y / 8;
@@ -2754,7 +2754,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	if (INTEL_INFO(dev)->gen >= 4) {
 		intel_crtc->dspaddr_offset =
 			intel_gen4_compute_page_offset(dev_priv,
-						       &x, &y, obj->tiling_mode,
+						       &x, &y, fb->modifier[0],
 						       pixel_size,
 						       fb->pitches[0]);
 		linear_offset -= intel_crtc->dspaddr_offset;
@@ -2859,7 +2859,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	intel_crtc->dspaddr_offset =
 		intel_gen4_compute_page_offset(dev_priv,
-					       &x, &y, obj->tiling_mode,
+					       &x, &y, fb->modifier[0],
 					       pixel_size,
 					       fb->pitches[0]);
 	linear_offset -= intel_crtc->dspaddr_offset;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0598932..1152566 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1138,8 +1138,8 @@ void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
 unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
 					     int *x, int *y,
-					     unsigned int tiling_mode,
-					     unsigned int bpp,
+					     uint64_t fb_modifier,
+					     unsigned int cpp,
 					     unsigned int pitch);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index b229c67..90e27c8 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -422,7 +422,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
 							&x, &y,
-							obj->tiling_mode,
+							fb->modifier[0],
 							pixel_size,
 							fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
@@ -556,7 +556,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset =
 		intel_gen4_compute_page_offset(dev_priv,
-					       &x, &y, obj->tiling_mode,
+					       &x, &y, fb->modifier[0],
 					       pixel_size, fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
@@ -694,7 +694,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	dvssurf_offset =
 		intel_gen4_compute_page_offset(dev_priv,
-					       &x, &y, obj->tiling_mode,
+					       &x, &y, fb->modifier[0],
 					       pixel_size, fb->pitches[0]);
 	linear_offset -= dvssurf_offset;
 
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 03/22] drm/i915: Factor out intel_tile_width()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
  2015-10-14 16:28 ` [PATCH 01/22] drm: Add drm_format_plane_width() and drm_format_plane_height() ville.syrjala
  2015-10-14 16:28 ` [PATCH 02/22] drm/i915: Pass modifier instead of tiling_mode to gen4_compute_page_offset() ville.syrjala
@ 2015-10-14 16:28 ` ville.syrjala
  2015-10-21 10:15   ` Daniel Vetter
  2015-10-14 16:28 ` [PATCH 04/22] drm/i915: Redo intel_tile_height() as intel_tile_size() / intel_tile_width() ville.syrjala
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Pull the tile width calculations from intel_fb_stride_alignment() into a
new function intel_tile_width().

Also take the opportunity to pass aroun dev_priv instead of dev to
intel_fb_stride_alignment().

v2: Reorder argumnents to be more consistent with other functions
    Change intel_fb_stride_alignment() to accept dev_priv instead of dev

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 76 +++++++++++++++++++++++-------------
 drivers/gpu/drm/i915/intel_drv.h     |  4 +-
 drivers/gpu/drm/i915/intel_sprite.c  |  2 +-
 3 files changed, 51 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6add8d1..c31fe47 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2214,6 +2214,41 @@ static bool need_vtd_wa(struct drm_device *dev)
 	return false;
 }
 
+static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
+				     uint64_t fb_modifier, unsigned int cpp)
+{
+	switch (fb_modifier) {
+	case DRM_FORMAT_MOD_NONE:
+		return cpp;
+	case I915_FORMAT_MOD_X_TILED:
+		return IS_GEN2(dev_priv) ? 128 : 512;
+	case I915_FORMAT_MOD_Y_TILED:
+		/* No need to check for old gens and Y tiling since this is
+		 * about the display engine and those will be blocked before
+		 * we get here.
+		 */
+		return 128;
+	case I915_FORMAT_MOD_Yf_TILED:
+		switch (cpp) {
+		case 1:
+			return 64;
+		case 2:
+		case 4:
+			return 128;
+		case 8:
+		case 16:
+			return 256;
+		default:
+			MISSING_CASE(cpp);
+			return cpp;
+		}
+		break;
+	default:
+		MISSING_CASE(fb_modifier);
+		return cpp;
+	}
+}
+
 unsigned int
 intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
 		  uint64_t fb_format_modifier, unsigned int plane)
@@ -2895,37 +2930,20 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	POSTING_READ(reg);
 }
 
-u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
-			      uint32_t pixel_format)
+u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
+			      uint64_t fb_modifier, uint32_t pixel_format)
 {
-	u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
-
 	/*
 	 * The stride is either expressed as a multiple of 64 bytes
 	 * chunks for linear buffers or in number of tiles for tiled
 	 * buffers.
 	 */
-	switch (fb_modifier) {
-	case DRM_FORMAT_MOD_NONE:
-		return 64;
-	case I915_FORMAT_MOD_X_TILED:
-		if (INTEL_INFO(dev)->gen == 2)
-			return 128;
-		return 512;
-	case I915_FORMAT_MOD_Y_TILED:
-		/* No need to check for old gens and Y tiling since this is
-		 * about the display engine and those will be blocked before
-		 * we get here.
-		 */
-		return 128;
-	case I915_FORMAT_MOD_Yf_TILED:
-		if (bits_per_pixel == 8)
-			return 64;
-		else
-			return 128;
-	default:
-		MISSING_CASE(fb_modifier);
+	if (fb_modifier == DRM_FORMAT_MOD_NONE) {
 		return 64;
+	} else {
+		unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
+
+		return intel_tile_width(dev_priv, fb_modifier, cpp);
 	}
 }
 
@@ -3106,7 +3124,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	plane_ctl |= skl_plane_ctl_rotation(rotation);
 
 	obj = intel_fb_obj(fb);
-	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
+	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
 					       fb->pixel_format);
 	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
 
@@ -9066,7 +9084,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
 	fb->width = ((val >> 0) & 0x1fff) + 1;
 
 	val = I915_READ(PLANE_STRIDE(pipe, 0));
-	stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
+	stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
 						fb->pixel_format);
 	fb->pitches[0] = (val & 0x3ff) * stride_mult;
 
@@ -11137,7 +11155,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
 	 * linear buffers or in number of tiles for tiled buffers.
 	 */
 	stride = fb->pitches[0] /
-		 intel_fb_stride_alignment(dev, fb->modifier[0],
+		 intel_fb_stride_alignment(dev_priv, fb->modifier[0],
 					   fb->pixel_format);
 
 	/*
@@ -14214,6 +14232,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
 				  struct drm_mode_fb_cmd2 *mode_cmd,
 				  struct drm_i915_gem_object *obj)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned int aligned_height;
 	int ret;
 	u32 pitch_limit, stride_alignment;
@@ -14255,7 +14274,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
 		return -EINVAL;
 	}
 
-	stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
+	stride_alignment = intel_fb_stride_alignment(dev_priv,
+						     mode_cmd->modifier[0],
 						     mode_cmd->pixel_format);
 	if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
 		DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1152566..98a8d31 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1017,8 +1017,8 @@ unsigned int intel_fb_align_height(struct drm_device *dev,
 				   uint64_t fb_format_modifier);
 void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire,
 			enum fb_op_origin origin);
-u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
-			      uint32_t pixel_format);
+u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
+			      uint64_t fb_modifier, uint32_t pixel_format);
 
 /* intel_audio.c */
 void intel_init_audio(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 90e27c8..3d96871 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -215,7 +215,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 				       pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
-	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
+	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
 					       fb->pixel_format);
 
 	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 04/22] drm/i915: Redo intel_tile_height() as intel_tile_size() / intel_tile_width()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (2 preceding siblings ...)
  2015-10-14 16:28 ` [PATCH 03/22] drm/i915: Factor out intel_tile_width() ville.syrjala
@ 2015-10-14 16:28 ` ville.syrjala
  2015-10-21 10:21   ` Daniel Vetter
  2015-10-14 16:28 ` [PATCH 05/22] drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size ville.syrjala
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

I find more usual to think about tile widths than heights, so changing
the intel_tile_height() to calculate the tile height as
tile_size/tile_width is easier than the opposite to the poor brain.

v2: Reorder arguments for consistency
    Constify dev_priv arguments

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 88 ++++++++++++------------------------
 drivers/gpu/drm/i915/intel_drv.h     |  5 +-
 drivers/gpu/drm/i915/intel_sprite.c  |  4 +-
 3 files changed, 34 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c31fe47..d028326 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2214,6 +2214,11 @@ static bool need_vtd_wa(struct drm_device *dev)
 	return false;
 }
 
+static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
+{
+	return IS_GEN2(dev_priv) ? 2048 : 4096;
+}
+
 static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
 				     uint64_t fb_modifier, unsigned int cpp)
 {
@@ -2249,67 +2254,34 @@ static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
 	}
 }
 
-unsigned int
-intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
-		  uint64_t fb_format_modifier, unsigned int plane)
+unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
+			       uint64_t fb_modifier, unsigned int cpp)
 {
-	unsigned int tile_height;
-	uint32_t pixel_bytes;
-
-	switch (fb_format_modifier) {
-	case DRM_FORMAT_MOD_NONE:
-		tile_height = 1;
-		break;
-	case I915_FORMAT_MOD_X_TILED:
-		tile_height = IS_GEN2(dev) ? 16 : 8;
-		break;
-	case I915_FORMAT_MOD_Y_TILED:
-		tile_height = 32;
-		break;
-	case I915_FORMAT_MOD_Yf_TILED:
-		pixel_bytes = drm_format_plane_cpp(pixel_format, plane);
-		switch (pixel_bytes) {
-		default:
-		case 1:
-			tile_height = 64;
-			break;
-		case 2:
-		case 4:
-			tile_height = 32;
-			break;
-		case 8:
-			tile_height = 16;
-			break;
-		case 16:
-			WARN_ONCE(1,
-				  "128-bit pixels are not supported for display!");
-			tile_height = 16;
-			break;
-		}
-		break;
-	default:
-		MISSING_CASE(fb_format_modifier);
-		tile_height = 1;
-		break;
-	}
-
-	return tile_height;
+	if (fb_modifier == DRM_FORMAT_MOD_NONE)
+		return 1;
+	else
+		return intel_tile_size(dev_priv) /
+			intel_tile_width(dev_priv, fb_modifier, cpp);
 }
 
 unsigned int
 intel_fb_align_height(struct drm_device *dev, unsigned int height,
-		      uint32_t pixel_format, uint64_t fb_format_modifier)
+		      uint32_t pixel_format, uint64_t fb_modifier)
 {
-	return ALIGN(height, intel_tile_height(dev, pixel_format,
-					       fb_format_modifier, 0));
+	unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
+	unsigned int tile_height = intel_tile_height(to_i915(dev), fb_modifier, cpp);
+
+	return ALIGN(height, tile_height);
 }
 
 static int
 intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
 			const struct drm_plane_state *plane_state)
 {
+	struct drm_i915_private *dev_priv = to_i915(fb->dev);
 	struct intel_rotation_info *info = &view->rotation_info;
 	unsigned int tile_height, tile_pitch;
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	*view = i915_ggtt_view_normal;
 
@@ -2327,22 +2299,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
 	info->uv_offset = fb->offsets[1];
 	info->fb_modifier = fb->modifier[0];
 
-	tile_height = intel_tile_height(fb->dev, fb->pixel_format,
-					fb->modifier[0], 0);
+	tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
 	tile_pitch = PAGE_SIZE / tile_height;
 	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
 	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
 	info->size = info->width_pages * info->height_pages * PAGE_SIZE;
 
 	if (info->pixel_format == DRM_FORMAT_NV12) {
-		tile_height = intel_tile_height(fb->dev, fb->pixel_format,
-						fb->modifier[0], 1);
+		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
+		tile_height = intel_tile_height(dev_priv, fb->modifier[1], cpp);
 		tile_pitch = PAGE_SIZE / tile_height;
-		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
-		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
-						     tile_height);
-		info->size_uv = info->width_pages_uv * info->height_pages_uv *
-				PAGE_SIZE;
+		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_pitch);
+		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
+		info->size_uv = info->width_pages_uv * info->height_pages_uv * PAGE_SIZE;
 	}
 
 	return 0;
@@ -3102,6 +3071,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
 	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
 	int scaler_id = -1;
+	int pixel_size;
 
 	plane_state = to_intel_plane_state(plane->state);
 
@@ -3112,6 +3082,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		return;
 	}
 
+	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+
 	plane_ctl = PLANE_CTL_ENABLE |
 		    PLANE_CTL_PIPE_GAMMA_ENABLE |
 		    PLANE_CTL_PIPE_CSC_ENABLE;
@@ -3144,8 +3116,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 
 	if (intel_rotation_90_or_270(rotation)) {
 		/* stride = Surface height in tiles */
-		tile_height = intel_tile_height(dev, fb->pixel_format,
-						fb->modifier[0], 0);
+		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
+						pixel_size);
 		stride = DIV_ROUND_UP(fb->height, tile_height);
 		x_offset = stride * tile_height - y - src_h;
 		y_offset = x;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 98a8d31..429f744 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1095,9 +1095,8 @@ int intel_plane_atomic_set_property(struct drm_plane *plane,
 int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 				    struct drm_plane_state *plane_state);
 
-unsigned int
-intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
-		  uint64_t fb_format_modifier, unsigned int plane);
+unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
+			       uint64_t fb_modifier, unsigned int cpp);
 
 static inline bool
 intel_rotation_90_or_270(unsigned int rotation)
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 3d96871..4a1a5f4 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -241,8 +241,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 
 	if (intel_rotation_90_or_270(rotation)) {
 		/* stride: Surface height in tiles */
-		tile_height = intel_tile_height(dev, fb->pixel_format,
-						fb->modifier[0], 0);
+		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
+						pixel_size);
 		stride = DIV_ROUND_UP(fb->height, tile_height);
 		plane_size = (src_w << 16) | src_h;
 		x_offset = stride * tile_height - y - (src_h + 1);
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 05/22] drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (3 preceding siblings ...)
  2015-10-14 16:28 ` [PATCH 04/22] drm/i915: Redo intel_tile_height() as intel_tile_size() / intel_tile_width() ville.syrjala
@ 2015-10-14 16:28 ` ville.syrjala
  2015-10-21 10:22   ` Daniel Vetter
  2015-10-14 16:28 ` [PATCH 06/22] drm/i915: Use intel_tile_{size, width, height}() in intel_gen4_compute_page_offset() ville.syrjala
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Use the actual tile size as to compute stuff in
intel_fill_fb_ggtt_view() instead of assuming it's PAGE_SIZE. I suppose
it doesn't matter since we don't use the results on gen2 platforms
where the tile size is 2k.

v2: Update due to CbCr plane

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d028326..c8b2907 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2280,8 +2280,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
 {
 	struct drm_i915_private *dev_priv = to_i915(fb->dev);
 	struct intel_rotation_info *info = &view->rotation_info;
-	unsigned int tile_height, tile_pitch;
-	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+	unsigned int tile_size, tile_width, tile_height, cpp;
 
 	*view = i915_ggtt_view_normal;
 
@@ -2299,19 +2298,24 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
 	info->uv_offset = fb->offsets[1];
 	info->fb_modifier = fb->modifier[0];
 
-	tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
-	tile_pitch = PAGE_SIZE / tile_height;
-	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
+	tile_size = intel_tile_size(dev_priv);
+
+	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+	tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
+	tile_height = tile_size / tile_width;
+
+	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
 	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
-	info->size = info->width_pages * info->height_pages * PAGE_SIZE;
+	info->size = info->width_pages * info->height_pages * tile_size;
 
 	if (info->pixel_format == DRM_FORMAT_NV12) {
 		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
-		tile_height = intel_tile_height(dev_priv, fb->modifier[1], cpp);
-		tile_pitch = PAGE_SIZE / tile_height;
-		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_pitch);
+		tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
+		tile_height = tile_size / tile_width;
+
+		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
 		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
-		info->size_uv = info->width_pages_uv * info->height_pages_uv * PAGE_SIZE;
+		info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
 	}
 
 	return 0;
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 06/22] drm/i915: Use intel_tile_{size, width, height}() in intel_gen4_compute_page_offset()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (4 preceding siblings ...)
  2015-10-14 16:28 ` [PATCH 05/22] drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size ville.syrjala
@ 2015-10-14 16:28 ` ville.syrjala
  2015-10-21 10:24   ` Daniel Vetter
  2015-10-14 16:28 ` [PATCH 07/22] drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/ ville.syrjala
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make intel_gen4_compute_page_offset() ready for other tiling formats
besied X-tile by getting the tile dimensions through
intel_tile_{size,width,height}().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c8b2907..509fcac 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2460,15 +2460,20 @@ unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
 					     unsigned int pitch)
 {
 	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
+		unsigned int tile_size, tile_width, tile_height;
 		unsigned int tile_rows, tiles;
 
-		tile_rows = *y / 8;
-		*y %= 8;
+		tile_size = intel_tile_size(dev_priv);
+		tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
+		tile_height = tile_size / tile_width;
+
+		tile_rows = *y / tile_height;
+		*y %= tile_height;
 
-		tiles = *x / (512/cpp);
-		*x %= 512/cpp;
+		tiles = *x / (tile_width/cpp);
+		*x %= tile_width/cpp;
 
-		return tile_rows * pitch * 8 + tiles * 4096;
+		return tile_rows * pitch * tile_height + tiles * tile_size;
 	} else {
 		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
 		unsigned int offset;
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 07/22] drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (5 preceding siblings ...)
  2015-10-14 16:28 ` [PATCH 06/22] drm/i915: Use intel_tile_{size, width, height}() in intel_gen4_compute_page_offset() ville.syrjala
@ 2015-10-14 16:28 ` ville.syrjala
  2015-10-21 10:45   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:28 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Since intel_gen4_compute_page_offset() can now handle tiling formats
all the way down to gen2, rename it to intel_compute_page_offset().
Not that we actually use it on gen2/3 since there's no DSPSURF etc.
registers which would take a page aligned address.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 24 +++++++++++-------------
 drivers/gpu/drm/i915/intel_drv.h     | 10 +++++-----
 drivers/gpu/drm/i915/intel_sprite.c  | 22 +++++++++-------------
 3 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 509fcac..75be66b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2453,11 +2453,11 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
 
 /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
  * is assumed to be a power-of-two. */
-unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
-					     int *x, int *y,
-					     uint64_t fb_modifier,
-					     unsigned int cpp,
-					     unsigned int pitch)
+unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
+					int *x, int *y,
+					uint64_t fb_modifier,
+					unsigned int cpp,
+					unsigned int pitch)
 {
 	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_size, tile_width, tile_height;
@@ -2766,10 +2766,9 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		intel_crtc->dspaddr_offset =
-			intel_gen4_compute_page_offset(dev_priv,
-						       &x, &y, fb->modifier[0],
-						       pixel_size,
-						       fb->pitches[0]);
+			intel_compute_page_offset(dev_priv, &x, &y,
+						  fb->modifier[0], pixel_size,
+						  fb->pitches[0]);
 		linear_offset -= intel_crtc->dspaddr_offset;
 	} else {
 		intel_crtc->dspaddr_offset = linear_offset;
@@ -2871,10 +2870,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	intel_crtc->dspaddr_offset =
-		intel_gen4_compute_page_offset(dev_priv,
-					       &x, &y, fb->modifier[0],
-					       pixel_size,
-					       fb->pitches[0]);
+		intel_compute_page_offset(dev_priv, &x, &y,
+					  fb->modifier[0], pixel_size,
+					  fb->pitches[0]);
 	linear_offset -= intel_crtc->dspaddr_offset;
 	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 429f744..a12ac95 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1135,11 +1135,11 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
 void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
-unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
-					     int *x, int *y,
-					     uint64_t fb_modifier,
-					     unsigned int cpp,
-					     unsigned int pitch);
+unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
+					int *x, int *y,
+					uint64_t fb_modifier,
+					unsigned int cpp,
+					unsigned int pitch);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
 void hsw_enable_pc8(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 4a1a5f4..6614adb 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -420,11 +420,9 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	crtc_h--;
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
-	sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
-							&x, &y,
-							fb->modifier[0],
-							pixel_size,
-							fb->pitches[0]);
+	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
+						   fb->modifier[0], pixel_size,
+						   fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
 	if (dplane->state->rotation == BIT(DRM_ROTATE_180)) {
@@ -554,10 +552,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
-	sprsurf_offset =
-		intel_gen4_compute_page_offset(dev_priv,
-					       &x, &y, fb->modifier[0],
-					       pixel_size, fb->pitches[0]);
+	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
+						   fb->modifier[0], pixel_size,
+						   fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
 	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
@@ -692,10 +689,9 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
-	dvssurf_offset =
-		intel_gen4_compute_page_offset(dev_priv,
-					       &x, &y, fb->modifier[0],
-					       pixel_size, fb->pitches[0]);
+	dvssurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
+						   fb->modifier[0], pixel_size,
+						   fb->pitches[0]);
 	linear_offset -= dvssurf_offset;
 
 	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (6 preceding siblings ...)
  2015-10-14 16:28 ` [PATCH 07/22] drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/ ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 10:53   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 09/22] drm/i915: Refactor intel_surf_alignment() ville.syrjala
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The page aligned surface address calculation needs to know which way
things are rotated. The contract now says that the caller must pass the
rotate x/y coordinates, as well as the tile_height aligned stride in
the tile_height direction. This will make it fairly simple to deal with
90/270 degree rotation on SKL+ where we have to deal with the rotated
view into the GTT.

v2: Pass rotation instead of bool even thoughwe only care about 0/180 vs. 90/270

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 62 ++++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_drv.h     |  3 +-
 drivers/gpu/drm/i915/intel_sprite.c  | 15 +++++----
 3 files changed, 64 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 75be66b..bd55d06 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2451,13 +2451,50 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
 	i915_gem_object_unpin_from_display_plane(obj, &view);
 }
 
-/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
- * is assumed to be a power-of-two. */
+/*
+ * Return the tile dimensions in pixel units matching
+ * the specified rotation angle.
+ */
+static void intel_rotate_tile_dims(unsigned int *tile_width,
+				   unsigned int *tile_height,
+				   unsigned int *pitch,
+				   unsigned int cpp,
+				   unsigned int rotation)
+{
+	if (intel_rotation_90_or_270(rotation)) {
+		WARN_ON(*pitch % *tile_height);
+
+		/* pixel units please */
+		*tile_width /= cpp;
+
+		/*
+		 * Coordinate space is rotated, orient
+		 * our tile dimensions the same way
+		 */
+		swap(*tile_width, *tile_height);
+	} else {
+		WARN_ON(*pitch % *tile_width);
+
+		/* pixel units please */
+		*tile_width /= cpp;
+		*pitch /= cpp;
+	}
+}
+
+/*
+ * Computes the linear offset to the base tile and adjusts
+ * x, y. bytes per pixel is assumed to be a power-of-two.
+ *
+ * In the 90/270 rotated case, x and y are assumed
+ * to be already rotated to match the rotated GTT view, and
+ * pitch is the tile_height aligned framebuffer height.
+ */
 unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
 					int *x, int *y,
 					uint64_t fb_modifier,
 					unsigned int cpp,
-					unsigned int pitch)
+					unsigned int pitch,
+					unsigned int rotation)
 {
 	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_size, tile_width, tile_height;
@@ -2467,13 +2504,16 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
 		tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
 		tile_height = tile_size / tile_width;
 
+		intel_rotate_tile_dims(&tile_width, &tile_height,
+				       &pitch, cpp, rotation);
+
 		tile_rows = *y / tile_height;
 		*y %= tile_height;
 
-		tiles = *x / (tile_width/cpp);
-		*x %= tile_width/cpp;
+		tiles = *x / tile_width;
+		*x %= tile_width;
 
-		return tile_rows * pitch * tile_height + tiles * tile_size;
+		return (tile_rows * (pitch / tile_width) + tiles) * tile_size;
 	} else {
 		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
 		unsigned int offset;
@@ -2685,6 +2725,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	bool visible = to_intel_plane_state(primary->state)->visible;
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
+	unsigned int rotation;
 	unsigned long linear_offset;
 	u32 dspcntr;
 	u32 reg = DSPCNTR(plane);
@@ -2704,6 +2745,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	if (WARN_ON(obj == NULL))
 		return;
 
+	rotation = crtc->primary->state->rotation;
 	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -2768,7 +2810,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 		intel_crtc->dspaddr_offset =
 			intel_compute_page_offset(dev_priv, &x, &y,
 						  fb->modifier[0], pixel_size,
-						  fb->pitches[0]);
+						  fb->pitches[0], rotation);
 		linear_offset -= intel_crtc->dspaddr_offset;
 	} else {
 		intel_crtc->dspaddr_offset = linear_offset;
@@ -2814,6 +2856,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	bool visible = to_intel_plane_state(primary->state)->visible;
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
+	unsigned int rotation;
 	unsigned long linear_offset;
 	u32 dspcntr;
 	u32 reg = DSPCNTR(plane);
@@ -2830,6 +2873,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	if (WARN_ON(obj == NULL))
 		return;
 
+	rotation = crtc->primary->state->rotation;
 	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -2872,9 +2916,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	intel_crtc->dspaddr_offset =
 		intel_compute_page_offset(dev_priv, &x, &y,
 					  fb->modifier[0], pixel_size,
-					  fb->pitches[0]);
+					  fb->pitches[0], rotation);
 	linear_offset -= intel_crtc->dspaddr_offset;
-	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
 
 		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a12ac95..ed47ca3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1139,7 +1139,8 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
 					int *x, int *y,
 					uint64_t fb_modifier,
 					unsigned int cpp,
-					unsigned int pitch);
+					unsigned int pitch,
+					unsigned int rotation);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
 void hsw_enable_pc8(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 6614adb..8eaebce 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -354,6 +354,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	int pipe = intel_plane->pipe;
 	int plane = intel_plane->plane;
 	u32 sprctl;
+	unsigned int rotation = dplane->state->rotation;
 	unsigned long sprsurf_offset, linear_offset;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
@@ -422,10 +423,10 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
 						   fb->modifier[0], pixel_size,
-						   fb->pitches[0]);
+						   fb->pitches[0], rotation);
 	linear_offset -= sprsurf_offset;
 
-	if (dplane->state->rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SP_ROTATE_180;
 
 		x += src_w;
@@ -491,6 +492,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	enum pipe pipe = intel_plane->pipe;
 	u32 sprctl, sprscale = 0;
+	unsigned int rotation = plane->state->rotation;
 	unsigned long sprsurf_offset, linear_offset;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
@@ -554,10 +556,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
 						   fb->modifier[0], pixel_size,
-						   fb->pitches[0]);
+						   fb->pitches[0], rotation);
 	linear_offset -= sprsurf_offset;
 
-	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SPRITE_ROTATE_180;
 
 		/* HSW and BDW does this automagically in hardware */
@@ -631,6 +633,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	int pipe = intel_plane->pipe;
+	unsigned int rotation = plane->state->rotation;
 	unsigned long dvssurf_offset, linear_offset;
 	u32 dvscntr, dvsscale;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
@@ -691,10 +694,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	dvssurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
 						   fb->modifier[0], pixel_size,
-						   fb->pitches[0]);
+						   fb->pitches[0], rotation);
 	linear_offset -= dvssurf_offset;
 
-	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		dvscntr |= DVS_ROTATE_180;
 
 		x += src_w;
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 09/22] drm/i915: Refactor intel_surf_alignment()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (7 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 10:54   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Pull the code to determine the surface alignment for both linear and
tiled surfaces into a separate function intel_surf_alignment(). This
will be used not only for the vma alignment but actually aligning
the plane SURF once SKL+ starts using intel_compute_page_offset()
(since SKL+ needs >4K alignment for tiled surfaces too).

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 45 +++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bd55d06..5f3abce 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2321,7 +2321,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
 	return 0;
 }
 
-static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
+static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
 {
 	if (INTEL_INFO(dev_priv)->gen >= 9)
 		return 256 * 1024;
@@ -2334,6 +2334,25 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
 		return 0;
 }
 
+static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv,
+					 uint64_t fb_modifier)
+{
+	switch (fb_modifier) {
+	case DRM_FORMAT_MOD_NONE:
+		return intel_linear_alignment(dev_priv);
+	case I915_FORMAT_MOD_X_TILED:
+		if (INTEL_INFO(dev_priv)->gen >= 9)
+			return 256 * 1024;
+		return 0;
+	case I915_FORMAT_MOD_Y_TILED:
+	case I915_FORMAT_MOD_Yf_TILED:
+		return 1 * 1024 * 1024;
+	default:
+		MISSING_CASE(fb_modifier);
+		return 0;
+	}
+}
+
 int
 intel_pin_and_fence_fb_obj(struct drm_plane *plane,
 			   struct drm_framebuffer *fb,
@@ -2350,29 +2369,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	switch (fb->modifier[0]) {
-	case DRM_FORMAT_MOD_NONE:
-		alignment = intel_linear_alignment(dev_priv);
-		break;
-	case I915_FORMAT_MOD_X_TILED:
-		if (INTEL_INFO(dev)->gen >= 9)
-			alignment = 256 * 1024;
-		else {
-			/* pin() will align the object as required by fence */
-			alignment = 0;
-		}
-		break;
-	case I915_FORMAT_MOD_Y_TILED:
-	case I915_FORMAT_MOD_Yf_TILED:
-		if (WARN_ONCE(INTEL_INFO(dev)->gen < 9,
-			  "Y tiling bo slipped through, driver bug!\n"))
-			return -EINVAL;
-		alignment = 1 * 1024 * 1024;
-		break;
-	default:
-		MISSING_CASE(fb->modifier[0]);
-		return -EINVAL;
-	}
+	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
 
 	ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
 	if (ret)
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (8 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 09/22] drm/i915: Refactor intel_surf_alignment() ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 11:22   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

SKL+ needs >4K alignment for tiled surfaces, so make
intel_compute_page_offset() handle it.

The way we do it is first we compute the closest tile boundary
as before, and then figure out how many tiles we need to go
to reach the desired alignment. The difference in the offset
is then added into the x/y offsets.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++++++++++----
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5f3abce..85e1473 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2479,6 +2479,39 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
 }
 
 /*
+ * Adjust the page 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.
+ * intel_rotate_tile_dims() gives exactly that.
+ */
+static void intel_adjust_page_offset(int *x, int *y,
+				     unsigned int tile_width,
+				     unsigned int tile_height,
+				     unsigned int tile_size,
+				     unsigned int pitch,
+				     unsigned int old_offset,
+				     unsigned int new_offset)
+{
+	unsigned int tiles;
+
+	WARN_ON(old_offset & (tile_size - 1));
+	WARN_ON(new_offset & (tile_size - 1));
+	WARN_ON(new_offset > old_offset);
+
+	tiles = (old_offset - new_offset) / tile_size;
+	if (tiles == 0)
+		return;
+
+	/* pitch in tiles */
+	pitch /= tile_width;
+
+	*y += tiles / pitch * tile_height;
+	*x += tiles % pitch * tile_width;
+}
+
+/*
  * Computes the linear offset to the base tile and adjusts
  * x, y. bytes per pixel is assumed to be a power-of-two.
  *
@@ -2493,6 +2526,12 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
 					unsigned int pitch,
 					unsigned int rotation)
 {
+	unsigned int offset, alignment;
+
+	alignment = intel_surf_alignment(dev_priv, fb_modifier);
+	if (alignment)
+		alignment--;
+
 	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_size, tile_width, tile_height;
 		unsigned int tile_rows, tiles;
@@ -2510,16 +2549,18 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
 		tiles = *x / tile_width;
 		*x %= tile_width;
 
-		return (tile_rows * (pitch / tile_width) + tiles) * tile_size;
-	} else {
-		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
-		unsigned int offset;
+		offset = (tile_rows * (pitch / tile_width) + tiles) * tile_size;
 
+		intel_adjust_page_offset(x, y, tile_width, tile_height,
+					 tile_size, pitch,
+					 offset, offset & ~alignment);
+	} else {
 		offset = *y * pitch + *x * cpp;
 		*y = (offset & alignment) / pitch;
 		*x = ((offset & alignment) - *y * pitch) / cpp;
-		return offset & ~alignment;
 	}
+
+	return offset & ~alignment;
 }
 
 static int i9xx_format_to_fourcc(int format)
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (9 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-15  9:08   ` Chris Wilson
                     ` (2 more replies)
  2015-10-14 16:29 ` [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly ville.syrjala
                   ` (11 subsequent siblings)
  22 siblings, 3 replies; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
rotation (to find the right GTT view for it), so no need to pass all
kinds of plane stuff.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++--------------------
 drivers/gpu/drm/i915/intel_drv.h     |  5 ++---
 drivers/gpu/drm/i915/intel_fbdev.c   |  2 +-
 3 files changed, 20 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 85e1473..80e9f2e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2275,8 +2275,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
 }
 
 static int
-intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
-			const struct drm_plane_state *plane_state)
+intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
+			const struct drm_framebuffer *fb,
+			unsigned int rotation)
 {
 	struct drm_i915_private *dev_priv = to_i915(fb->dev);
 	struct intel_rotation_info *info = &view->rotation_info;
@@ -2284,10 +2285,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
 
 	*view = i915_ggtt_view_normal;
 
-	if (!plane_state)
-		return 0;
-
-	if (!intel_rotation_90_or_270(plane_state->rotation))
+	if (!intel_rotation_90_or_270(rotation))
 		return 0;
 
 	*view = i915_ggtt_view_rotated;
@@ -2354,9 +2352,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
 }
 
 int
-intel_pin_and_fence_fb_obj(struct drm_plane *plane,
-			   struct drm_framebuffer *fb,
-			   const struct drm_plane_state *plane_state,
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
+			   unsigned int rotation,
 			   struct intel_engine_cs *pipelined,
 			   struct drm_i915_gem_request **pipelined_request)
 {
@@ -2371,7 +2368,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
 
 	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
 
-	ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
+	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
 	if (ret)
 		return ret;
 
@@ -2432,8 +2429,7 @@ err_interruptible:
 	return ret;
 }
 
-static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
-			       const struct drm_plane_state *plane_state)
+static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
 {
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct i915_ggtt_view view;
@@ -2441,7 +2437,7 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
 
 	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
 
-	ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
+	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
 	WARN_ONCE(ret, "Couldn't get view from plane state!");
 
 	i915_gem_object_unpin_fence(obj);
@@ -10780,7 +10776,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
 	struct drm_plane *primary = crtc->base.primary;
 
 	mutex_lock(&dev->struct_mutex);
-	intel_unpin_fb_obj(work->old_fb, primary->state);
+	intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
 	drm_gem_object_unreference(&work->pending_flip_obj->base);
 
 	if (work->flip_queued_req)
@@ -11521,8 +11517,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	 * synchronisation, so all we want here is to pin the framebuffer
 	 * into the display plane and skip any waits.
 	 */
-	ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
-					 crtc->primary->state,
+	ret = intel_pin_and_fence_fb_obj(fb, primary->state->rotation,
 					 mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring, &request);
 	if (ret)
 		goto cleanup_pending;
@@ -11573,7 +11568,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	return 0;
 
 cleanup_unpin:
-	intel_unpin_fb_obj(fb, crtc->primary->state);
+	intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
 cleanup_pending:
 	if (request)
 		i915_gem_request_cancel(request);
@@ -13457,7 +13452,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
 		if (ret)
 			DRM_DEBUG_KMS("failed to attach phys object\n");
 	} else {
-		ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL, NULL);
+		ret = intel_pin_and_fence_fb_obj(fb, new_state->rotation,
+						 NULL, NULL);
 	}
 
 	if (ret == 0)
@@ -13488,7 +13484,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
 	if (plane->type != DRM_PLANE_TYPE_CURSOR ||
 	    !INTEL_INFO(dev)->cursor_needs_physical) {
 		mutex_lock(&dev->struct_mutex);
-		intel_unpin_fb_obj(old_state->fb, old_state);
+		intel_unpin_fb_obj(old_state->fb, old_state->rotation);
 		mutex_unlock(&dev->struct_mutex);
 	}
 }
@@ -15474,9 +15470,8 @@ void intel_modeset_gem_init(struct drm_device *dev)
 			continue;
 
 		mutex_lock(&dev->struct_mutex);
-		ret = intel_pin_and_fence_fb_obj(c->primary,
-						 c->primary->fb,
-						 c->primary->state,
+		ret = intel_pin_and_fence_fb_obj(c->primary->fb,
+						 c->primary->state->rotation,
 						 NULL, NULL);
 		mutex_unlock(&dev->struct_mutex);
 		if (ret) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ed47ca3..b0d92e0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1067,9 +1067,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 void intel_release_load_detect_pipe(struct drm_connector *connector,
 				    struct intel_load_detect_pipe *old,
 				    struct drm_modeset_acquire_ctx *ctx);
-int intel_pin_and_fence_fb_obj(struct drm_plane *plane,
-			       struct drm_framebuffer *fb,
-			       const struct drm_plane_state *plane_state,
+int intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
+			       unsigned int rotation,
 			       struct intel_engine_cs *pipelined,
 			       struct drm_i915_gem_request **pipelined_request);
 struct drm_framebuffer *
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 4fd5fdf..6bef820 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -161,7 +161,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
 	}
 
 	/* Flush everything out, we'll be doing GTT only from now on */
-	ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL, NULL, NULL);
+	ret = intel_pin_and_fence_fb_obj(fb, BIT(DRM_ROTATE_0), NULL, NULL);
 	if (ret) {
 		DRM_ERROR("failed to pin obj: %d\n", ret);
 		goto out_fb;
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (10 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-15 11:15   ` Tvrtko Ursulin
  2015-10-14 16:29 ` [PATCH 13/22] drm/i915: Move the partial and rotated view data into the same union ville.syrjala
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Just for clarity set the type for i915_ggtt_view_normal explicitly.

While at it fix the indentation fail for i915_ggtt_view_rotated.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 620d57e..71acc71 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -95,9 +95,11 @@
 static int
 i915_get_ggtt_vma_pages(struct i915_vma *vma);
 
-const struct i915_ggtt_view i915_ggtt_view_normal;
+const struct i915_ggtt_view i915_ggtt_view_normal = {
+	.type = I915_GGTT_VIEW_NORMAL,
+};
 const struct i915_ggtt_view i915_ggtt_view_rotated = {
-        .type = I915_GGTT_VIEW_ROTATED
+	.type = I915_GGTT_VIEW_ROTATED,
 };
 
 static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 13/22] drm/i915: Move the partial and rotated view data into the same union
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (11 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 11:30   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal ville.syrjala
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Each gtt view only has a single type, and so don't need to contain data
for both rotated and partial views. So we can move the data into the
same union to avoid wasting space.

Also rename 'rotation_info' to 'rotated' to match the view type exactly,
this should avoid confusion which union members is valid for each view
type. Also make the union anonymous to avoid the .params. stuff all
over.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c      | 10 +++++-----
 drivers/gpu/drm/i915/i915_gem_gtt.c  | 12 ++++++------
 drivers/gpu/drm/i915/i915_gem_gtt.h  | 11 ++++-------
 drivers/gpu/drm/i915/intel_display.c |  4 ++--
 4 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e57061a..b93ed18 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1772,12 +1772,12 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 		memset(&view, 0, sizeof(view));
 		view.type = I915_GGTT_VIEW_PARTIAL;
-		view.params.partial.offset = rounddown(page_offset, chunk_size);
-		view.params.partial.size =
+		view.partial.offset = rounddown(page_offset, chunk_size);
+		view.partial.size =
 			min_t(unsigned int,
 			      chunk_size,
 			      (vma->vm_end - vma->vm_start)/PAGE_SIZE -
-			      view.params.partial.offset);
+			      view.partial.offset);
 	}
 
 	/* Now pin it into the GTT if needed */
@@ -1805,10 +1805,10 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 		 * having accessed it before (at this partials' range).
 		 */
 		unsigned long base = vma->vm_start +
-				     (view.params.partial.offset << PAGE_SHIFT);
+				     (view.partial.offset << PAGE_SHIFT);
 		unsigned int i;
 
-		for (i = 0; i < view.params.partial.size; i++) {
+		for (i = 0; i < view.partial.size; i++) {
 			ret = vm_insert_pfn(vma, base + i * PAGE_SIZE, pfn + i);
 			if (ret)
 				break;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 71acc71..e0baff2 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3282,7 +3282,7 @@ static struct sg_table *
 intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
 			  struct drm_i915_gem_object *obj)
 {
-	struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
+	struct intel_rotation_info *rot_info = &ggtt_view->rotated;
 	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
 	unsigned int size_pages_uv;
 	struct sg_page_iter sg_iter;
@@ -3380,16 +3380,16 @@ intel_partial_pages(const struct i915_ggtt_view *view,
 	if (!st)
 		goto err_st_alloc;
 
-	ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
+	ret = sg_alloc_table(st, view->partial.size, GFP_KERNEL);
 	if (ret)
 		goto err_sg_alloc;
 
 	sg = st->sgl;
 	st->nents = 0;
 	for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
-		view->params.partial.offset)
+		view->partial.offset)
 	{
-		if (st->nents >= view->params.partial.size)
+		if (st->nents >= view->partial.size)
 			break;
 
 		sg_set_page(sg, NULL, PAGE_SIZE, 0);
@@ -3514,9 +3514,9 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
 	if (view->type == I915_GGTT_VIEW_NORMAL) {
 		return obj->base.size;
 	} else if (view->type == I915_GGTT_VIEW_ROTATED) {
-		return view->rotation_info.size;
+		return view->rotated.size;
 	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
-		return view->params.partial.size << PAGE_SHIFT;
+		return view->partial.size << PAGE_SHIFT;
 	} else {
 		WARN_ONCE(1, "GGTT view %u not implemented!\n", view->type);
 		return obj->base.size;
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index a216397..caa182f 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -151,17 +151,14 @@ struct intel_rotation_info {
 struct i915_ggtt_view {
 	enum i915_ggtt_view_type type;
 
+	struct sg_table *pages;
+
 	union {
+		struct intel_rotation_info rotated;
 		struct {
 			u64 offset;
 			unsigned int size;
 		} partial;
-	} params;
-
-	struct sg_table *pages;
-
-	union {
-		struct intel_rotation_info rotation_info;
 	};
 };
 
@@ -557,7 +554,7 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
 	if (a->type != b->type)
 		return false;
 	if (a->type == I915_GGTT_VIEW_PARTIAL)
-		return !memcmp(&a->params, &b->params, sizeof(a->params));
+		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
 	return true;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 80e9f2e..ce346cfe 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2280,7 +2280,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
 			unsigned int rotation)
 {
 	struct drm_i915_private *dev_priv = to_i915(fb->dev);
-	struct intel_rotation_info *info = &view->rotation_info;
+	struct intel_rotation_info *info = &view->rotated;
 	unsigned int tile_size, tile_width, tile_height, cpp;
 
 	*view = i915_ggtt_view_normal;
@@ -3020,7 +3020,7 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 	offset = (unsigned char *)vma->node.start;
 
 	if (plane == 1) {
-		offset += vma->ggtt_view.rotation_info.uv_start_page *
+		offset += vma->ggtt_view.rotated.uv_start_page *
 			  PAGE_SIZE;
 	}
 
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (12 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 13/22] drm/i915: Move the partial and rotated view data into the same union ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-15 11:18   ` Tvrtko Ursulin
  2015-10-21 11:36   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 15/22] drm/i915: Pass the dma_addr_t array as const to rotate_pages() ville.syrjala
                   ` (8 subsequent siblings)
  22 siblings, 2 replies; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

In case we have multiple different rotated views into the same object,
each one may need its own vma due to being of different sizes. So don't
treat all rotated views as equal.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index caa182f..68de734 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -553,6 +553,8 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
 
 	if (a->type != b->type)
 		return false;
+	if (a->type == I915_GGTT_VIEW_ROTATED)
+		return !memcmp(&a->rotated, &b->rotated, sizeof(a->rotated));
 	if (a->type == I915_GGTT_VIEW_PARTIAL)
 		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
 	return true;
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 15/22] drm/i915: Pass the dma_addr_t array as const to rotate_pages()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (13 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 11:36   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 16/22] drm/i915: Pass stride " ville.syrjala
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

rotate_pages() doesn't modify the passed in dma addresses, so make
them const.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index e0baff2..365a8c6 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3247,7 +3247,7 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
 }
 
 static struct scatterlist *
-rotate_pages(dma_addr_t *in, unsigned int offset,
+rotate_pages(const dma_addr_t *in, unsigned int offset,
 	     unsigned int width, unsigned int height,
 	     struct sg_table *st, struct scatterlist *sg)
 {
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 16/22] drm/i915: Pass stride to rotate_pages()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (14 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 15/22] drm/i915: Pass the dma_addr_t array as const to rotate_pages() ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-14 16:29 ` [PATCH 17/22] drm/i915: Pass rotation_info to intel_rotate_fb_obj_pages() ville.syrjala
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Pass stride in addition to width and height to rotate_pages(). For now
width and stride are the same, but once framebuffer offsets enter the
scene that may no longer be the case.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 365a8c6..73ca67d 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3249,6 +3249,7 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
 static struct scatterlist *
 rotate_pages(const dma_addr_t *in, unsigned int offset,
 	     unsigned int width, unsigned int height,
+	     unsigned int stride,
 	     struct sg_table *st, struct scatterlist *sg)
 {
 	unsigned int column, row;
@@ -3260,7 +3261,7 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
 	}
 
 	for (column = 0; column < width; column++) {
-		src_idx = width * (height - 1) + column;
+		src_idx = stride * (height - 1) + column;
 		for (row = 0; row < height; row++) {
 			st->nents++;
 			/* We don't need the pages, but need to initialize
@@ -3271,7 +3272,7 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
 			sg_dma_address(sg) = in[offset + src_idx];
 			sg_dma_len(sg) = PAGE_SIZE;
 			sg = sg_next(sg);
-			src_idx -= width;
+			src_idx -= stride;
 		}
 	}
 
@@ -3324,6 +3325,7 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
 	/* Rotate the pages. */
 	sg = rotate_pages(page_addr_list, 0,
 		     rot_info->width_pages, rot_info->height_pages,
+		     rot_info->width_pages,
 		     st, NULL);
 
 	/* Append the UV plane if NV12. */
@@ -3339,6 +3341,7 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
 		rotate_pages(page_addr_list, uv_start_page,
 			     rot_info->width_pages_uv,
 			     rot_info->height_pages_uv,
+			     rot_info->width_pages_uv,
 			     st, sg);
 	}
 
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 17/22] drm/i915: Pass rotation_info to intel_rotate_fb_obj_pages()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (15 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 16/22] drm/i915: Pass stride " ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-14 16:29 ` [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_rotate_fb_obj_pages() doens't need the entire gtt view, just the
rotation info suffices.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 73ca67d..bb95b86 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3280,10 +3280,9 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
 }
 
 static struct sg_table *
-intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
+intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
 			  struct drm_i915_gem_object *obj)
 {
-	struct intel_rotation_info *rot_info = &ggtt_view->rotated;
 	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
 	unsigned int size_pages_uv;
 	struct sg_page_iter sg_iter;
@@ -3423,7 +3422,7 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma)
 		vma->ggtt_view.pages = vma->obj->pages;
 	else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
 		vma->ggtt_view.pages =
-			intel_rotate_fb_obj_pages(&vma->ggtt_view, vma->obj);
+			intel_rotate_fb_obj_pages(&vma->ggtt_view.rotated, vma->obj);
 	else if (vma->ggtt_view.type == I915_GGTT_VIEW_PARTIAL)
 		vma->ggtt_view.pages =
 			intel_partial_pages(&vma->ggtt_view, vma->obj);
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (16 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 17/22] drm/i915: Pass rotation_info to intel_rotate_fb_obj_pages() ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-14 16:43   ` Daniel Vetter
  2015-10-21 11:41   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 19/22] drm/i915: Don't leak framebuffer_references if drm_framebuffer_init() fails ville.syrjala
                   ` (4 subsequent siblings)
  22 siblings, 2 replies; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We convert the fb->offsets[] into x/y offsets, so they must be
(macro)pixel aligned.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ce346cfe..70e6e27 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14284,6 +14284,36 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
 	}
 }
 
+static int intel_fb_check_offsets(const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	uint32_t format = mode_cmd->pixel_format;
+	int i;
+
+	for (i = 0; i < drm_format_num_planes(format); i++) {
+		unsigned int cpp;
+
+		switch (format) {
+		case DRM_FORMAT_YUYV:
+		case DRM_FORMAT_UYVY:
+		case DRM_FORMAT_YVYU:
+		case DRM_FORMAT_VYUY:
+			cpp = 4;
+			break;
+		default:
+			cpp = drm_format_plane_cpp(format, i);
+			break;
+		}
+
+		if (mode_cmd->offsets[i] % cpp) {
+			DRM_DEBUG("fb plane %d offset 0x%08x not (macro)pixel aligned\n",
+				  i, mode_cmd->offsets[i]);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static int intel_framebuffer_init(struct drm_device *dev,
 				  struct intel_framebuffer *intel_fb,
 				  struct drm_mode_fb_cmd2 *mode_cmd,
@@ -14410,9 +14440,9 @@ static int intel_framebuffer_init(struct drm_device *dev,
 		return -EINVAL;
 	}
 
-	/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
-	if (mode_cmd->offsets[0] != 0)
-		return -EINVAL;
+	ret = intel_fb_check_offsets(mode_cmd);
+	if (ret)
+		return ret;
 
 	aligned_height = intel_fb_align_height(dev, mode_cmd->height,
 					       mode_cmd->pixel_format,
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 19/22] drm/i915: Don't leak framebuffer_references if drm_framebuffer_init() fails
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (17 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 11:42   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 20/22] drm/i915: Pass drm_frambuffer to intel_compute_page_offset() ville.syrjala
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Don't increment obj->framebuffer_references until we know we actually
managed to create the framebuffer.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 70e6e27..0cfedf9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14453,7 +14453,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
 
 	drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
 	intel_fb->obj = obj;
-	intel_fb->obj->framebuffer_references++;
 
 	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
 	if (ret) {
@@ -14461,6 +14460,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
 		return ret;
 	}
 
+	intel_fb->obj->framebuffer_references++;
+
 	return 0;
 }
 
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 20/22] drm/i915: Pass drm_frambuffer to intel_compute_page_offset()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (18 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 19/22] drm/i915: Don't leak framebuffer_references if drm_framebuffer_init() fails ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 11:43   ` Daniel Vetter
  2015-10-14 16:29 ` [PATCH 21/22] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_compute_page_offsets() gets passed a bunch of the framebuffer
metadate sepearately. Just pass the framebuffer itself to make life
simpler for the caller, and make it less likely they would make a
mistake in the order of the arguments (as most as just unsigned ints and
such).

We still pass the pitch explicitly since for 90/270 degree rotation
the caller has to pass in the right thing.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 15 +++++++--------
 drivers/gpu/drm/i915/intel_drv.h     |  6 ++----
 drivers/gpu/drm/i915/intel_sprite.c  |  9 +++------
 3 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0cfedf9..028dc4a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2515,13 +2515,14 @@ static void intel_adjust_page_offset(int *x, int *y,
  * to be already rotated to match the rotated GTT view, and
  * pitch is the tile_height aligned framebuffer height.
  */
-unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
-					int *x, int *y,
-					uint64_t fb_modifier,
-					unsigned int cpp,
+unsigned long intel_compute_page_offset(int *x, int *y,
+					const struct drm_framebuffer *fb, int plane,
 					unsigned int pitch,
 					unsigned int rotation)
 {
+	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+	uint64_t fb_modifier = fb->modifier[plane];
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
 	unsigned int offset, alignment;
 
 	alignment = intel_surf_alignment(dev_priv, fb_modifier);
@@ -2842,8 +2843,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		intel_crtc->dspaddr_offset =
-			intel_compute_page_offset(dev_priv, &x, &y,
-						  fb->modifier[0], pixel_size,
+			intel_compute_page_offset(&x, &y, fb, 0,
 						  fb->pitches[0], rotation);
 		linear_offset -= intel_crtc->dspaddr_offset;
 	} else {
@@ -2948,8 +2948,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	intel_crtc->dspaddr_offset =
-		intel_compute_page_offset(dev_priv, &x, &y,
-					  fb->modifier[0], pixel_size,
+		intel_compute_page_offset(&x, &y, fb, 0,
 					  fb->pitches[0], rotation);
 	linear_offset -= intel_crtc->dspaddr_offset;
 	if (rotation == BIT(DRM_ROTATE_180)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b0d92e0..36d049d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1134,10 +1134,8 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
 void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
-unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
-					int *x, int *y,
-					uint64_t fb_modifier,
-					unsigned int cpp,
+unsigned long intel_compute_page_offset(int *x, int *y,
+					const struct drm_framebuffer *fb, int plane,
 					unsigned int pitch,
 					unsigned int rotation);
 void intel_prepare_reset(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 8eaebce..828c3eb 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -421,8 +421,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	crtc_h--;
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
-	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
-						   fb->modifier[0], pixel_size,
+	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
 	linear_offset -= sprsurf_offset;
 
@@ -554,8 +553,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
-	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
-						   fb->modifier[0], pixel_size,
+	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
 	linear_offset -= sprsurf_offset;
 
@@ -692,8 +690,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	linear_offset = y * fb->pitches[0] + x * pixel_size;
-	dvssurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
-						   fb->modifier[0], pixel_size,
+	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
 	linear_offset -= dvssurf_offset;
 
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 21/22] drm/i915: Rewrite fb rotation GTT handling
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (19 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 20/22] drm/i915: Pass drm_frambuffer to intel_compute_page_offset() ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-15 17:59   ` [PATCH v2 " ville.syrjala
  2015-10-14 16:29 ` [PATCH 22/22] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
  2015-10-14 16:59 ` [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic Daniel Vetter
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling reasier for the plane code

To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.

To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].

While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.

When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.

For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.

After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c  |  66 ++---
 drivers/gpu/drm/i915/i915_gem_gtt.h  |  14 +-
 drivers/gpu/drm/i915/intel_display.c | 452 ++++++++++++++++++++++++-----------
 drivers/gpu/drm/i915/intel_drv.h     |  32 ++-
 drivers/gpu/drm/i915/intel_sprite.c  | 104 ++++----
 5 files changed, 407 insertions(+), 261 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index bb95b86..98aee6c 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3255,11 +3255,6 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
 	unsigned int column, row;
 	unsigned int src_idx;
 
-	if (!sg) {
-		st->nents = 0;
-		sg = st->sgl;
-	}
-
 	for (column = 0; column < width; column++) {
 		src_idx = stride * (height - 1) + column;
 		for (row = 0; row < height; row++) {
@@ -3280,16 +3275,14 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
 }
 
 static struct sg_table *
-intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
+intel_rotate_fb_obj_pages(const struct intel_rotation_info *info,
 			  struct drm_i915_gem_object *obj)
 {
-	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
-	unsigned int size_pages_uv;
+	unsigned int size = intel_rotation_info_size(info);
 	struct sg_page_iter sg_iter;
 	unsigned long i;
 	dma_addr_t *page_addr_list;
 	struct sg_table *st;
-	unsigned int uv_start_page;
 	struct scatterlist *sg;
 	int ret = -ENOMEM;
 
@@ -3299,57 +3292,32 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
 	if (!page_addr_list)
 		return ERR_PTR(ret);
 
-	/* Account for UV plane with NV12. */
-	if (rot_info->pixel_format == DRM_FORMAT_NV12)
-		size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
-	else
-		size_pages_uv = 0;
-
 	/* Allocate target SG list. */
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st)
 		goto err_st_alloc;
 
-	ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
+	ret = sg_alloc_table(st, size, GFP_KERNEL);
 	if (ret)
 		goto err_sg_alloc;
 
 	/* Populate source page list from the object. */
 	i = 0;
 	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
-		page_addr_list[i] = sg_page_iter_dma_address(&sg_iter);
-		i++;
+		page_addr_list[i++] = sg_page_iter_dma_address(&sg_iter);
 	}
 
-	/* Rotate the pages. */
-	sg = rotate_pages(page_addr_list, 0,
-		     rot_info->width_pages, rot_info->height_pages,
-		     rot_info->width_pages,
-		     st, NULL);
-
-	/* Append the UV plane if NV12. */
-	if (rot_info->pixel_format == DRM_FORMAT_NV12) {
-		uv_start_page = size_pages;
-
-		/* Check for tile-row un-alignment. */
-		if (offset_in_page(rot_info->uv_offset))
-			uv_start_page--;
-
-		rot_info->uv_start_page = uv_start_page;
+	st->nents = 0;
+	sg = st->sgl;
 
-		rotate_pages(page_addr_list, uv_start_page,
-			     rot_info->width_pages_uv,
-			     rot_info->height_pages_uv,
-			     rot_info->width_pages_uv,
-			     st, sg);
+	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++) {
+		sg = rotate_pages(page_addr_list, info->plane[i].offset,
+				  info->plane[i].width, info->plane[i].height,
+				  info->plane[i].stride, st, sg);
 	}
 
-	DRM_DEBUG_KMS(
-		      "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
-		      obj->base.size, rot_info->pitch, rot_info->height,
-		      rot_info->pixel_format, rot_info->width_pages,
-		      rot_info->height_pages, size_pages + size_pages_uv,
-		      size_pages);
+	DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages)\n",
+		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
 
 	drm_free_large(page_addr_list);
 
@@ -3360,12 +3328,8 @@ err_sg_alloc:
 err_st_alloc:
 	drm_free_large(page_addr_list);
 
-	DRM_DEBUG_KMS(
-		      "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
-		      obj->base.size, ret, rot_info->pitch, rot_info->height,
-		      rot_info->pixel_format, rot_info->width_pages,
-		      rot_info->height_pages, size_pages + size_pages_uv,
-		      size_pages);
+	DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
+		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
 	return ERR_PTR(ret);
 }
 
@@ -3516,7 +3480,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
 	if (view->type == I915_GGTT_VIEW_NORMAL) {
 		return obj->base.size;
 	} else if (view->type == I915_GGTT_VIEW_ROTATED) {
-		return view->rotated.size;
+		return intel_rotation_info_size(&view->rotated) << PAGE_SHIFT;
 	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
 		return view->partial.size << PAGE_SHIFT;
 	} else {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 68de734..ea28f7d 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -136,16 +136,10 @@ enum i915_ggtt_view_type {
 };
 
 struct intel_rotation_info {
-	unsigned int height;
-	unsigned int pitch;
-	unsigned int uv_offset;
-	uint32_t pixel_format;
-	uint64_t fb_modifier;
-	unsigned int width_pages, height_pages;
-	uint64_t size;
-	unsigned int width_pages_uv, height_pages_uv;
-	uint64_t size_uv;
-	unsigned int uv_start_page;
+	struct {
+		/* tiles */
+		unsigned int width, height, stride, offset;
+	} plane[2];
 };
 
 struct i915_ggtt_view {
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 028dc4a..8c7dc03 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2274,49 +2274,28 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
 	return ALIGN(height, tile_height);
 }
 
-static int
-intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
-			const struct drm_framebuffer *fb,
-			unsigned int rotation)
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *info)
 {
-	struct drm_i915_private *dev_priv = to_i915(fb->dev);
-	struct intel_rotation_info *info = &view->rotated;
-	unsigned int tile_size, tile_width, tile_height, cpp;
-
-	*view = i915_ggtt_view_normal;
-
-	if (!intel_rotation_90_or_270(rotation))
-		return 0;
-
-	*view = i915_ggtt_view_rotated;
-
-	info->height = fb->height;
-	info->pixel_format = fb->pixel_format;
-	info->pitch = fb->pitches[0];
-	info->uv_offset = fb->offsets[1];
-	info->fb_modifier = fb->modifier[0];
-
-	tile_size = intel_tile_size(dev_priv);
-
-	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-	tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
-	tile_height = tile_size / tile_width;
+	unsigned int size = 0;
+	int i;
 
-	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
-	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
-	info->size = info->width_pages * info->height_pages * tile_size;
+	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++)
+		size += info->plane[i].width * info->plane[i].height;
 
-	if (info->pixel_format == DRM_FORMAT_NV12) {
-		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
-		tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
-		tile_height = tile_size / tile_width;
+	return size;
+}
 
-		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
-		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
-		info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
+static void
+intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
+			const struct drm_framebuffer *fb,
+			unsigned int rotation)
+{
+	if (intel_rotation_90_or_270(rotation)) {
+		*view = i915_ggtt_view_rotated;
+		view->rotated = to_intel_framebuffer(fb)->info;
+	} else {
+		*view = i915_ggtt_view_normal;
 	}
-
-	return 0;
 }
 
 static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
@@ -2368,9 +2347,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 
 	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
 
-	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
-	if (ret)
-		return ret;
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
 	/* Note that the w/a also requires 64 PTE of padding following the
 	 * bo. We currently fill all unused PTE with the shadow page and so
@@ -2433,18 +2410,31 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation
 {
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct i915_ggtt_view view;
-	int ret;
 
 	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
 
-	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
-	WARN_ONCE(ret, "Couldn't get view from plane state!");
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
 	i915_gem_object_unpin_fence(obj);
 	i915_gem_object_unpin_from_display_plane(obj, &view);
 }
 
 /*
+ * Convert the x/y offsets into a linear offset.
+ * Only valid with 0/180 degree rotation, which is fine since linear
+ * offset is only used with linear buffers on pre-hsw and tiled buffers
+ * with gen2/3, and 90/270 degree rotations isn't supported on any of them.
+ */
+unsigned int intel_fb_xy_to_linear(int x, int y,
+				   const struct drm_framebuffer *fb, int plane)
+{
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+	unsigned int pitch = fb->pitches[plane];
+
+	return y * pitch + x * cpp;
+}
+
+/*
  * Return the tile dimensions in pixel units matching
  * the specified rotation angle.
  */
@@ -2475,6 +2465,55 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
 }
 
 /*
+ * Add the x/y offsets derived from fb->offsets[] to the user
+ * specified plane src x/y offsets. The resulting x/y offsets
+ * specify the start of scanout from the beginning of the gtt mapping.
+ */
+void intel_add_fb_offsets(int *x, int *y,
+			  const struct drm_framebuffer *fb, int plane,
+			  unsigned int rotation)
+
+{
+	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+	const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+	unsigned int pitch;
+
+	if (intel_rotation_90_or_270(rotation)) {
+		pitch = intel_fb->plane[plane].rotated.pitch;
+
+		*x += intel_fb->plane[plane].rotated.x;
+		*y += intel_fb->plane[plane].rotated.y;
+	} else {
+		pitch = fb->pitches[plane];
+
+		*x += intel_fb->plane[plane].normal.x;
+		*y += intel_fb->plane[plane].normal.y;
+	}
+
+	/* minimize x */
+	if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
+		unsigned int tile_size, tile_width, tile_height;
+
+		tile_size = intel_tile_size(dev_priv);
+		tile_width = intel_tile_width(dev_priv, fb->modifier[plane], cpp);
+		tile_height = tile_size / tile_width;
+
+		intel_rotate_tile_dims(&tile_width, &tile_height,
+				       &pitch, cpp, rotation);
+
+		*y += *x / pitch * tile_height;
+		*x  = *x % pitch;
+	} else {
+		/* in pixels */
+		pitch /= cpp;
+
+		*y += *x / pitch;
+		*x  = *x % pitch;
+	}
+}
+
+/*
  * Adjust the page offset by moving the difference into
  * the x/y offsets.
  *
@@ -2514,20 +2553,23 @@ static void intel_adjust_page_offset(int *x, int *y,
  * In the 90/270 rotated case, x and y are assumed
  * to be already rotated to match the rotated GTT view, and
  * pitch is the tile_height aligned framebuffer height.
+ *
+ * This function is used when computing the derived information
+ * under intel_framebuffer, so using any of that information
+ * here is not allowed. Anything under drm_framebuffer can be
+ * used. This is why the user has to pass in the pitch since it
+ * is specified in the rotated orientation.
  */
-unsigned long intel_compute_page_offset(int *x, int *y,
-					const struct drm_framebuffer *fb, int plane,
-					unsigned int pitch,
-					unsigned int rotation)
+static unsigned int _intel_compute_page_offset(const struct drm_i915_private *dev_priv,
+					       int *x, int *y,
+					       const struct drm_framebuffer *fb, int plane,
+					       unsigned int pitch,
+					       unsigned int rotation,
+					       unsigned int alignment)
 {
-	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
 	uint64_t fb_modifier = fb->modifier[plane];
 	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
-	unsigned int offset, alignment;
-
-	alignment = intel_surf_alignment(dev_priv, fb_modifier);
-	if (alignment)
-		alignment--;
+	unsigned int offset;
 
 	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_size, tile_width, tile_height;
@@ -2560,6 +2602,145 @@ unsigned long intel_compute_page_offset(int *x, int *y,
 	return offset & ~alignment;
 }
 
+unsigned int intel_compute_page_offset(int *x, int *y,
+				       const struct drm_framebuffer *fb, int plane,
+				       unsigned int pitch,
+				       unsigned int rotation)
+{
+	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+	unsigned int alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
+
+	return _intel_compute_page_offset(dev_priv, x, y, fb, plane, pitch,
+					  rotation, alignment ? (alignment - 1) : 0);
+}
+
+/* Convert the fb->offset[] linear offset into x/y offsets */
+static void intel_fb_offset_to_xy(int *x, int *y,
+				  const struct drm_framebuffer *fb, int plane)
+{
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+	unsigned int pitch = fb->pitches[plane];
+	unsigned int linear_offset = fb->offsets[plane];
+
+	*y = linear_offset / pitch;
+	*x = linear_offset % pitch / cpp;
+}
+
+static int
+intel_fill_fb_info(struct drm_i915_private *dev_priv,
+		   struct drm_framebuffer *fb)
+{
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+	struct intel_rotation_info *info = &intel_fb->info;
+	unsigned int tile_size;
+	unsigned int gtt_offset_rotated = 0;
+	unsigned int max_size = 0;
+	uint32_t format = fb->pixel_format;
+	int i, num_planes = drm_format_num_planes(format);
+
+	tile_size = intel_tile_size(dev_priv);
+
+	for (i = 0; i < num_planes; i++) {
+		unsigned int width, height;
+		unsigned int cpp, offset, size;
+		int x, y;
+
+		cpp = drm_format_plane_cpp(format, i);
+		width = drm_format_plane_width(fb->width, format, i);
+		height = drm_format_plane_height(fb->height, format, i);
+
+		intel_fb_offset_to_xy(&x, &y, fb, i);
+
+		/*
+		 * First pixel of the framebuffer from
+		 * the start of the normal gtt mapping.
+		 */
+		intel_fb->plane[i].normal.x = x;
+		intel_fb->plane[i].normal.y = y;
+
+		offset = _intel_compute_page_offset(dev_priv, &x, &y,
+						    fb, 0, fb->pitches[i],
+						    BIT(DRM_ROTATE_0),
+						    tile_size);
+		offset /= tile_size;
+		DRM_DEBUG("page offset %u pages\n", offset);
+
+		if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
+			unsigned int tile_width, tile_height;
+			unsigned int pitch;
+			struct drm_rect r;
+
+			tile_width = intel_tile_width(dev_priv, fb->modifier[i], cpp);
+			tile_height = tile_size / tile_width;
+
+			info->plane[i].offset = offset;
+			info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width);
+			info->plane[i].width = DIV_ROUND_UP((x + width) * cpp, tile_width);
+			info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
+
+
+			intel_fb->plane[i].rotated.pitch =
+				info->plane[i].height * tile_height;
+
+			/* how many tiles does this plane need */
+			size = info->plane[i].stride * info->plane[i].height;
+			/*
+			 * If the plane isn't horizontally tile aligned,
+			 * we need one more tile.
+			 */
+			if (x != 0)
+				size++;
+
+			pitch = intel_fb->plane[i].rotated.pitch;
+
+			/* rotate the x/y offsets to match the GTT view */
+			r.x1 = x;
+			r.y1 = y;
+			r.x2 = x + width;
+			r.y2 = y + height;
+			drm_rect_rotate(&r, width, pitch, BIT(DRM_ROTATE_270));
+			x = r.x1;
+			y = r.y1;
+
+			intel_rotate_tile_dims(&tile_width, &tile_height, &pitch,
+					       cpp, BIT(DRM_ROTATE_270));
+
+			/*
+			 * We only keep the x/y offsets, so push all of the
+			 * gtt offset into the x/y offsets.
+			 */
+			intel_adjust_page_offset(&x, &y, tile_width, tile_height,
+						 tile_size, pitch,
+						 gtt_offset_rotated * tile_size, 0);
+
+			gtt_offset_rotated += info->plane[i].width * info->plane[i].height;
+
+			/*
+			 * First pixel of the framebuffer from
+			 * the start of the rotated gtt mapping.
+			 */
+			intel_fb->plane[i].rotated.x = x;
+			intel_fb->plane[i].rotated.y = y;
+		} else {
+			size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
+					    x * cpp, tile_size);
+		}
+		DRM_DEBUG("%d offset %u, size %u, stride %u, height %u\n",
+			  i, offset, size, info->plane[i].stride, info->plane[i].height);
+
+		/* how many tiles in total needed in the bo */
+		max_size = max(max_size, offset + size);
+	}
+
+	if (max_size * tile_size > to_intel_framebuffer(fb)->obj->base.size) {
+		DRM_DEBUG("fb too big for bo (need %u bytes, have %zu bytes)\n",
+			  max_size * tile_size, to_intel_framebuffer(fb)->obj->base.size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int i9xx_format_to_fourcc(int format)
 {
 	switch (format) {
@@ -2757,11 +2938,12 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_plane *primary = crtc->primary;
+	struct intel_framebuffer *intel_fb;
 	bool visible = to_intel_plane_state(primary->state)->visible;
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
 	unsigned int rotation;
-	unsigned long linear_offset;
+	unsigned int linear_offset;
 	u32 dspcntr;
 	u32 reg = DSPCNTR(plane);
 	int pixel_size;
@@ -2780,6 +2962,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	if (WARN_ON(obj == NULL))
 		return;
 
+	intel_fb = to_intel_framebuffer(fb);
 	rotation = crtc->primary->state->rotation;
 	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
@@ -2839,30 +3022,25 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	if (IS_G4X(dev))
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_INFO(dev)->gen >= 4)
 		intel_crtc->dspaddr_offset =
 			intel_compute_page_offset(&x, &y, fb, 0,
 						  fb->pitches[0], rotation);
-		linear_offset -= intel_crtc->dspaddr_offset;
-	} else {
-		intel_crtc->dspaddr_offset = linear_offset;
-	}
 
 	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
 
 		x += (intel_crtc->config->pipe_src_w - 1);
 		y += (intel_crtc->config->pipe_src_h - 1);
-
-		/* Finding the last pixel of the last line of the display
-		data and adding to linear_offset*/
-		linear_offset +=
-			(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
-			(intel_crtc->config->pipe_src_w - 1) * pixel_size;
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
+	if (INTEL_INFO(dev)->gen < 4)
+		intel_crtc->dspaddr_offset = linear_offset;
+
 	intel_crtc->adjusted_x = x;
 	intel_crtc->adjusted_y = y;
 
@@ -2871,7 +3049,8 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	if (INTEL_INFO(dev)->gen >= 4) {
 		I915_WRITE(DSPSURF(plane),
-			   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+			   intel_surf_gtt_offset(fb, 0, rotation) +
+			   intel_crtc->dspaddr_offset);
 		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
 		I915_WRITE(DSPLINOFF(plane), linear_offset);
 	} else
@@ -2887,11 +3066,12 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_plane *primary = crtc->primary;
+	struct intel_framebuffer *intel_fb;
 	bool visible = to_intel_plane_state(primary->state)->visible;
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
 	unsigned int rotation;
-	unsigned long linear_offset;
+	unsigned int linear_offset;
 	u32 dspcntr;
 	u32 reg = DSPCNTR(plane);
 	int pixel_size;
@@ -2907,6 +3087,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	if (WARN_ON(obj == NULL))
 		return;
 
+	intel_fb = to_intel_framebuffer(fb);
 	rotation = crtc->primary->state->rotation;
 	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
@@ -2946,26 +3127,22 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	intel_crtc->dspaddr_offset =
 		intel_compute_page_offset(&x, &y, fb, 0,
 					  fb->pitches[0], rotation);
-	linear_offset -= intel_crtc->dspaddr_offset;
+
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
 
 		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
 			x += (intel_crtc->config->pipe_src_w - 1);
 			y += (intel_crtc->config->pipe_src_h - 1);
-
-			/* Finding the last pixel of the last line of the display
-			data and adding to linear_offset*/
-			linear_offset +=
-				(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
-				(intel_crtc->config->pipe_src_w - 1) * pixel_size;
 		}
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	intel_crtc->adjusted_x = x;
 	intel_crtc->adjusted_y = y;
 
@@ -2973,7 +3150,8 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	I915_WRITE(DSPSURF(plane),
-		   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+		   intel_surf_gtt_offset(fb, 0, rotation) +
+		   intel_crtc->dspaddr_offset);
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
 	} else {
@@ -3000,30 +3178,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
 	}
 }
 
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
-				     struct drm_i915_gem_object *obj,
-				     unsigned int plane)
+unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
+				   unsigned int rotation)
 {
-	const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
-	struct i915_vma *vma;
-	unsigned char *offset;
-
-	if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
-		view = &i915_ggtt_view_rotated;
-
-	vma = i915_gem_obj_to_ggtt_view(obj, view);
-	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
-		view->type))
-		return -1;
-
-	offset = (unsigned char *)vma->node.start;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	struct i915_ggtt_view view;
 
-	if (plane == 1) {
-		offset += vma->ggtt_view.rotated.uv_start_page *
-			  PAGE_SIZE;
-	}
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
-	return (unsigned long)offset;
+	return i915_gem_obj_ggtt_offset_view(obj, &view);
 }
 
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3142,18 +3305,16 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_plane *plane = crtc->primary;
+	struct intel_framebuffer *intel_fb;
 	bool visible = to_intel_plane_state(plane->state)->visible;
-	struct drm_i915_gem_object *obj;
 	int pipe = intel_crtc->pipe;
 	u32 plane_ctl, stride_div, stride;
-	u32 tile_height, plane_offset, plane_size;
 	unsigned int rotation;
-	int x_offset, y_offset;
 	unsigned long surf_addr;
 	struct intel_crtc_state *crtc_state = intel_crtc->config;
 	struct intel_plane_state *plane_state;
-	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
-	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
+	int src_w, src_h;
+	int dst_x, dst_y, dst_w, dst_h;
 	int scaler_id = -1;
 	int pixel_size;
 
@@ -3166,6 +3327,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		return;
 	}
 
+	intel_fb = to_intel_framebuffer(fb);
 	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	plane_ctl = PLANE_CTL_ENABLE |
@@ -3179,16 +3341,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	rotation = plane->state->rotation;
 	plane_ctl |= skl_plane_ctl_rotation(rotation);
 
-	obj = intel_fb_obj(fb);
-	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
-					       fb->pixel_format);
-	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
-
-	WARN_ON(drm_rect_width(&plane_state->src) == 0);
-
 	scaler_id = plane_state->scaler_id;
-	src_x = plane_state->src.x1 >> 16;
-	src_y = plane_state->src.y1 >> 16;
 	src_w = drm_rect_width(&plane_state->src) >> 16;
 	src_h = drm_rect_height(&plane_state->src) >> 16;
 	dst_x = plane_state->dst.x1;
@@ -3196,31 +3349,48 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	dst_w = drm_rect_width(&plane_state->dst);
 	dst_h = drm_rect_height(&plane_state->dst);
 
-	WARN_ON(x != src_x || y != src_y);
-
 	if (intel_rotation_90_or_270(rotation)) {
-		/* stride = Surface height in tiles */
-		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
-						pixel_size);
-		stride = DIV_ROUND_UP(fb->height, tile_height);
-		x_offset = stride * tile_height - y - src_h;
-		y_offset = x;
-		plane_size = (src_w - 1) << 16 | (src_h - 1);
+		struct drm_rect r = {
+			.x1 = x,
+			.x2 = x + src_w,
+			.y1 = y,
+			.y2 = y + src_h,
+		};
+
+		/* Rotate src coordinates to match rotated GTT view */
+		drm_rect_rotate(&r, fb->width, fb->height, DRM_ROTATE_270);
+
+		x = r.x1;
+		y = r.y1;
+		src_w = drm_rect_width(&r);
+		src_h = drm_rect_height(&r);
+
+		stride_div = intel_tile_height(dev_priv, fb->modifier[0],
+					       pixel_size);
+		stride = intel_fb->plane[0].rotated.pitch;
 	} else {
-		stride = fb->pitches[0] / stride_div;
-		x_offset = x;
-		y_offset = y;
-		plane_size = (src_h - 1) << 16 | (src_w - 1);
+		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+						       fb->pixel_format);
+		stride = fb->pitches[0];
 	}
-	plane_offset = y_offset << 16 | x_offset;
 
-	intel_crtc->adjusted_x = x_offset;
-	intel_crtc->adjusted_y = y_offset;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
+	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
+					      stride, rotation);
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	dst_w--;
+	dst_h--;
+
+	intel_crtc->adjusted_x = x;
+	intel_crtc->adjusted_y = y;
 
 	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
-	I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
-	I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
-	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
+	I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
+	I915_WRITE(PLANE_STRIDE(pipe, 0), stride / stride_div);
+	I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w);
 
 	if (scaler_id >= 0) {
 		uint32_t ps_ctrl = 0;
@@ -3237,7 +3407,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);
 	}
 
-	I915_WRITE(PLANE_SURF(pipe, 0), surf_addr);
+	I915_WRITE(PLANE_SURF(pipe, 0),
+		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
 
 	POSTING_READ(PLANE_SURF(pipe, 0));
 }
@@ -11521,8 +11692,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	if (ret)
 		goto cleanup_pending;
 
-	work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
-						  obj, 0);
+	work->gtt_offset = intel_surf_gtt_offset(fb, 0, primary->state->rotation);
 	work->gtt_offset += intel_crtc->dspaddr_offset;
 
 	if (mmio_flip) {
@@ -14319,7 +14489,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
 				  struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	unsigned int aligned_height;
 	int ret;
 	u32 pitch_limit, stride_alignment;
 
@@ -14443,16 +14612,13 @@ static int intel_framebuffer_init(struct drm_device *dev,
 	if (ret)
 		return ret;
 
-	aligned_height = intel_fb_align_height(dev, mode_cmd->height,
-					       mode_cmd->pixel_format,
-					       mode_cmd->modifier[0]);
-	/* FIXME drm helper for size checks (especially planar formats)? */
-	if (obj->base.size < aligned_height * mode_cmd->pitches[0])
-		return -EINVAL;
-
 	drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
 	intel_fb->obj = obj;
 
+	ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
+	if (ret)
+		return ret;
+
 	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
 	if (ret) {
 		DRM_ERROR("framebuffer init failed %d\n", ret);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 36d049d..395afd3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -118,6 +118,19 @@ enum intel_output_type {
 struct intel_framebuffer {
 	struct drm_framebuffer base;
 	struct drm_i915_gem_object *obj;
+	struct intel_rotation_info info;
+
+	struct {
+		struct {
+			/* pixels */
+			unsigned int x, y;
+		} normal;
+		struct {
+			/* pixels */
+			unsigned int x, y;
+			unsigned int pitch;
+		} rotated;
+	} plane[2];
 };
 
 struct intel_fbdev {
@@ -1028,6 +1041,12 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv);
 void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *info);
+unsigned int intel_fb_xy_to_linear(int x, int y,
+				   const struct drm_framebuffer *fb, int plane);
+void intel_add_fb_offsets(int *x, int *y,
+			  const struct drm_framebuffer *fb, int plane,
+			  unsigned int rotation);
 extern const struct drm_plane_funcs intel_plane_funcs;
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
 int intel_pch_rawclk(struct drm_device *dev);
@@ -1134,10 +1153,10 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
 void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
-unsigned long intel_compute_page_offset(int *x, int *y,
-					const struct drm_framebuffer *fb, int plane,
-					unsigned int pitch,
-					unsigned int rotation);
+unsigned int intel_compute_page_offset(int *x, int *y,
+				       const struct drm_framebuffer *fb, int plane,
+				       unsigned int pitch,
+				       unsigned int rotation);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
 void hsw_enable_pc8(struct drm_i915_private *dev_priv);
@@ -1174,9 +1193,8 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
 
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
-				     struct drm_i915_gem_object *obj,
-				     unsigned int plane);
+unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
+				   unsigned int rotation);
 
 u32 skl_plane_ctl_format(uint32_t pixel_format);
 u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 828c3eb..552c01d 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -188,17 +188,15 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	struct drm_device *dev = drm_plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
-	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	const int pipe = intel_plane->pipe;
 	const int plane = intel_plane->plane + 1;
 	u32 plane_ctl, stride_div, stride;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(drm_plane->state)->ckey;
-	unsigned long surf_addr;
-	u32 tile_height, plane_offset, plane_size;
+	unsigned int surf_addr;
 	unsigned int rotation;
-	int x_offset, y_offset;
 	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
 	int scaler_id;
 
@@ -215,17 +213,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 				       pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
-	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
-					       fb->pixel_format);
-
 	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
 
-	/* Sizes are 0 based */
-	src_w--;
-	src_h--;
-	crtc_w--;
-	crtc_h--;
-
 	if (key->flags) {
 		I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
 		I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
@@ -237,27 +226,43 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
 
-	surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
-
 	if (intel_rotation_90_or_270(rotation)) {
-		/* stride: Surface height in tiles */
-		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
-						pixel_size);
-		stride = DIV_ROUND_UP(fb->height, tile_height);
-		plane_size = (src_w << 16) | src_h;
-		x_offset = stride * tile_height - y - (src_h + 1);
-		y_offset = x;
+		struct drm_rect r = {
+			.x1 = x,
+			.x2 = x + src_w,
+			.y1 = y,
+			.y2 = y + src_h,
+		};
+
+		/* Rotate src coordinates to match rotated GTT view */
+		drm_rect_rotate(&r, fb->width, fb->height, DRM_ROTATE_270);
+
+		x = r.x1;
+		y = r.y1;
+		src_w = drm_rect_width(&r);
+		src_h = drm_rect_height(&r);
+
+		stride_div = intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
+		stride = intel_fb->plane[0].rotated.pitch;
 	} else {
-		stride = fb->pitches[0] / stride_div;
-		plane_size = (src_h << 16) | src_w;
-		x_offset = x;
-		y_offset = y;
+		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+						       fb->pixel_format);
+		stride = fb->pitches[0];
 	}
-	plane_offset = y_offset << 16 | x_offset;
 
-	I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
-	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
-	I915_WRITE(PLANE_SIZE(pipe, plane), plane_size);
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
+	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
+					      stride, rotation);
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	crtc_w--;
+	crtc_h--;
+
+	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
+	I915_WRITE(PLANE_STRIDE(pipe, plane), stride / stride_div);
+	I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
 
 	/* program plane scaler */
 	if (scaler_id >= 0) {
@@ -279,7 +284,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	}
 
 	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
-	I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
+	I915_WRITE(PLANE_SURF(pipe, plane),
+		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
 	POSTING_READ(PLANE_SURF(pipe, plane));
 }
 
@@ -355,8 +361,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	int plane = intel_plane->plane;
 	u32 sprctl;
 	unsigned int rotation = dplane->state->rotation;
-	unsigned long sprsurf_offset, linear_offset;
-	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+	unsigned int sprsurf_offset, linear_offset;
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(dplane->state)->ckey;
 
@@ -420,19 +425,19 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	crtc_w--;
 	crtc_h--;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
-	linear_offset -= sprsurf_offset;
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SP_ROTATE_180;
 
 		x += src_w;
 		y += src_h;
-		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	if (key->flags) {
 		I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
 		I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
@@ -457,8 +462,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 
 	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
 	I915_WRITE(SPCNTR(pipe, plane), sprctl);
-	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
-		   sprsurf_offset);
+	I915_WRITE(SPSURF(pipe, plane),
+		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
 	POSTING_READ(SPSURF(pipe, plane));
 }
 
@@ -492,8 +497,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	enum pipe pipe = intel_plane->pipe;
 	u32 sprctl, sprscale = 0;
 	unsigned int rotation = plane->state->rotation;
-	unsigned long sprsurf_offset, linear_offset;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+	unsigned int sprsurf_offset, linear_offset;
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(plane->state)->ckey;
 
@@ -552,10 +557,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (crtc_w != src_w || crtc_h != src_h)
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
-	linear_offset -= sprsurf_offset;
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SPRITE_ROTATE_180;
@@ -564,11 +568,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
 			x += src_w;
 			y += src_h;
-			linear_offset += src_h * fb->pitches[0] +
-				src_w * pixel_size;
 		}
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	if (key->flags) {
 		I915_WRITE(SPRKEYVAL(pipe), key->min_value);
 		I915_WRITE(SPRKEYMAX(pipe), key->max_value);
@@ -597,7 +601,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		I915_WRITE(SPRSCALE(pipe), sprscale);
 	I915_WRITE(SPRCTL(pipe), sprctl);
 	I915_WRITE(SPRSURF(pipe),
-		   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
+		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -632,9 +636,9 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	int pipe = intel_plane->pipe;
 	unsigned int rotation = plane->state->rotation;
-	unsigned long dvssurf_offset, linear_offset;
-	u32 dvscntr, dvsscale;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+	unsigned int dvssurf_offset, linear_offset;
+	u32 dvscntr, dvsscale;
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(plane->state)->ckey;
 
@@ -689,19 +693,19 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (crtc_w != src_w || crtc_h != src_h)
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
-	linear_offset -= dvssurf_offset;
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		dvscntr |= DVS_ROTATE_180;
 
 		x += src_w;
 		y += src_h;
-		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	if (key->flags) {
 		I915_WRITE(DVSKEYVAL(pipe), key->min_value);
 		I915_WRITE(DVSKEYMAX(pipe), key->max_value);
@@ -725,7 +729,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	I915_WRITE(DVSSCALE(pipe), dvsscale);
 	I915_WRITE(DVSCNTR(pipe), dvscntr);
 	I915_WRITE(DVSSURF(pipe),
-		   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
+		   intel_surf_gtt_offset(fb, 0, rotation) + dvssurf_offset);
 	POSTING_READ(DVSSURF(pipe));
 }
 
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH 22/22] drm/i915: Don't pass pitch to intel_compute_page_offset()
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (20 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 21/22] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
@ 2015-10-14 16:29 ` ville.syrjala
  2015-10-21 12:06   ` Daniel Vetter
  2015-10-14 16:59 ` [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic Daniel Vetter
  22 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-14 16:29 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

intel_compute_page_offset() can dig up the correct pitch from the fb
itself, no need for the caller to pass it in.

A bit of extra care is needed for the lower level
_intel_compute_page_offset() since that one gets called before the
rotated pitch under intel_fb is populated. Note that we don't actually
call it with anything but DRM_ROTATE_0 there so we wouldn't actually
look up the rotated pitch there, but still, leave the pitch as something
the caller has to pass to _intel_compute_page_offset() as an
indicator that something is a bit special.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 32 +++++++++++++++++---------------
 drivers/gpu/drm/i915/intel_drv.h     |  1 -
 drivers/gpu/drm/i915/intel_sprite.c  | 26 +++++++++++---------------
 3 files changed, 28 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8c7dc03..15dbe48 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2604,11 +2604,16 @@ static unsigned int _intel_compute_page_offset(const struct drm_i915_private *de
 
 unsigned int intel_compute_page_offset(int *x, int *y,
 				       const struct drm_framebuffer *fb, int plane,
-				       unsigned int pitch,
 				       unsigned int rotation)
 {
 	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
 	unsigned int alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
+	unsigned int pitch;
+
+	if (intel_rotation_90_or_270(rotation))
+		pitch = to_intel_framebuffer(fb)->plane[plane].rotated.pitch;
+	else
+		pitch = fb->pitches[plane];
 
 	return _intel_compute_page_offset(dev_priv, x, y, fb, plane, pitch,
 					  rotation, alignment ? (alignment - 1) : 0);
@@ -3026,8 +3031,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 
 	if (INTEL_INFO(dev)->gen >= 4)
 		intel_crtc->dspaddr_offset =
-			intel_compute_page_offset(&x, &y, fb, 0,
-						  fb->pitches[0], rotation);
+			intel_compute_page_offset(&x, &y, fb, 0, rotation);
 
 	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
@@ -3129,8 +3133,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 
 	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	intel_crtc->dspaddr_offset =
-		intel_compute_page_offset(&x, &y, fb, 0,
-					  fb->pitches[0], rotation);
+		intel_compute_page_offset(&x, &y, fb, 0, rotation);
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
@@ -3308,7 +3311,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	struct intel_framebuffer *intel_fb;
 	bool visible = to_intel_plane_state(plane->state)->visible;
 	int pipe = intel_crtc->pipe;
-	u32 plane_ctl, stride_div, stride;
+	u32 plane_ctl, stride;
 	unsigned int rotation;
 	unsigned long surf_addr;
 	struct intel_crtc_state *crtc_state = intel_crtc->config;
@@ -3365,18 +3368,17 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		src_w = drm_rect_width(&r);
 		src_h = drm_rect_height(&r);
 
-		stride_div = intel_tile_height(dev_priv, fb->modifier[0],
-					       pixel_size);
-		stride = intel_fb->plane[0].rotated.pitch;
+		stride = intel_fb->plane[0].rotated.pitch /
+			intel_tile_height(dev_priv, fb->modifier[0],
+					  pixel_size);
 	} else {
-		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
-						       fb->pixel_format);
-		stride = fb->pitches[0];
+		stride = fb->pitches[0] /
+			intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+						  fb->pixel_format);
 	}
 
 	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
-	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
-					      stride, rotation);
+	surf_addr = intel_compute_page_offset(&x, &y, fb, 0, rotation);
 
 	/* Sizes are 0 based */
 	src_w--;
@@ -3389,7 +3391,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 
 	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
 	I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
-	I915_WRITE(PLANE_STRIDE(pipe, 0), stride / stride_div);
+	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
 	I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w);
 
 	if (scaler_id >= 0) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 395afd3..af9861a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1155,7 +1155,6 @@ void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
 unsigned int intel_compute_page_offset(int *x, int *y,
 				       const struct drm_framebuffer *fb, int plane,
-				       unsigned int pitch,
 				       unsigned int rotation);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 552c01d..c4b7226 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -191,7 +191,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	const int pipe = intel_plane->pipe;
 	const int plane = intel_plane->plane + 1;
-	u32 plane_ctl, stride_div, stride;
+	u32 plane_ctl, stride;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(drm_plane->state)->ckey;
@@ -242,17 +242,16 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 		src_w = drm_rect_width(&r);
 		src_h = drm_rect_height(&r);
 
-		stride_div = intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
-		stride = intel_fb->plane[0].rotated.pitch;
+		stride = intel_fb->plane[0].rotated.pitch /
+			intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
 	} else {
-		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
-						       fb->pixel_format);
-		stride = fb->pitches[0];
+		stride = fb->pitches[0] /
+			intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+						  fb->pixel_format);
 	}
 
 	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
-	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
-					      stride, rotation);
+	surf_addr = intel_compute_page_offset(&x, &y, fb, 0, rotation);
 
 	/* Sizes are 0 based */
 	src_w--;
@@ -261,7 +260,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	crtc_h--;
 
 	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
-	I915_WRITE(PLANE_STRIDE(pipe, plane), stride / stride_div);
+	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
 	I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
 
 	/* program plane scaler */
@@ -426,8 +425,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	crtc_h--;
 
 	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
-	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
-						   fb->pitches[0], rotation);
+	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0, rotation);
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SP_ROTATE_180;
@@ -558,8 +556,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
-	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
-						   fb->pitches[0], rotation);
+	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0, rotation);
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SPRITE_ROTATE_180;
@@ -694,8 +691,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
-	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
-						   fb->pitches[0], rotation);
+	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0, rotation);
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		dvscntr |= DVS_ROTATE_180;
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* Re: [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned
  2015-10-14 16:29 ` [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
@ 2015-10-14 16:43   ` Daniel Vetter
  2015-10-21 11:41   ` Daniel Vetter
  1 sibling, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-14 16:43 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:10PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We convert the fb->offsets[] into x/y offsets, so they must be
> (macro)pixel aligned.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 36 +++++++++++++++++++++++++++++++++---
>  1 file changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ce346cfe..70e6e27 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14284,6 +14284,36 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
>  	}
>  }
>  
> +static int intel_fb_check_offsets(const struct drm_mode_fb_cmd2 *mode_cmd)
> +{
> +	uint32_t format = mode_cmd->pixel_format;
> +	int i;
> +
> +	for (i = 0; i < drm_format_num_planes(format); i++) {
> +		unsigned int cpp;
> +
> +		switch (format) {
> +		case DRM_FORMAT_YUYV:
> +		case DRM_FORMAT_UYVY:
> +		case DRM_FORMAT_YVYU:
> +		case DRM_FORMAT_VYUY:
> +			cpp = 4;
> +			break;
> +		default:
> +			cpp = drm_format_plane_cpp(format, i);
> +			break;

Might be worth it to extract this into a drm helper. gallium also has the
concept of a pixel block size, and it's _really_ nice imo.
-Daniel

> +		}
> +
> +		if (mode_cmd->offsets[i] % cpp) {
> +			DRM_DEBUG("fb plane %d offset 0x%08x not (macro)pixel aligned\n",
> +				  i, mode_cmd->offsets[i]);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static int intel_framebuffer_init(struct drm_device *dev,
>  				  struct intel_framebuffer *intel_fb,
>  				  struct drm_mode_fb_cmd2 *mode_cmd,
> @@ -14410,9 +14440,9 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  		return -EINVAL;
>  	}
>  
> -	/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
> -	if (mode_cmd->offsets[0] != 0)
> -		return -EINVAL;
> +	ret = intel_fb_check_offsets(mode_cmd);
> +	if (ret)
> +		return ret;
>  
>  	aligned_height = intel_fb_align_height(dev, mode_cmd->height,
>  					       mode_cmd->pixel_format,
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic
  2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
                   ` (21 preceding siblings ...)
  2015-10-14 16:29 ` [PATCH 22/22] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
@ 2015-10-14 16:59 ` Daniel Vetter
  2015-10-21 12:09   ` Daniel Vetter
  22 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-14 16:59 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:28:52PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> So while reviewing the NV12 stuff it became clear to me no one
> had really given fb->offsets[] handling any serious thought.
> So this patch series aims to fix that. We now treat fb->offsets[]
> as a linear offset always. One clear benefit over treating it as
> a linear offset as opposed to a raw byte offset is that we don't
> have to think about the layout of bytes within the tile at all.
> 
> The series also generalizes the page rotation to be format agnostic,
> the caller just specifies the desired geometry in pages for each
> plane, and the rotation code builds up the sg. The intel_rotation_info
> then just contains the minimal amount of information needed to
> do the page rotation.
> 
> SKL+ also gets changed to use the compute_page_offset stuff so that
> the plane SURF register will contain the closes (properly aligned)
> page boundary, and the x/y offsets deal with whatever is left over.
> The plane code for the other platforms also gets simpler in the end
> I think. Also the 90/270 rotation handling becomes rather trivial
> for the plane code.
> 
> I should still write some decent tests to exercise fb->offsets[].
> 
> Series available here:
> git://github.com/vsyrjala/linux.git fb_offsets

As mentioned on irc patches 13&14 need to me unified with my 3 patch
series, but otherwise lgtm overall.
-Daniel

> 
> Ville Syrjälä (22):
>   drm: Add drm_format_plane_width() and drm_format_plane_height()
>   drm/i915: Pass modifier instead of tiling_mode to
>     gen4_compute_page_offset()
>   drm/i915: Factor out intel_tile_width()
>   drm/i915: Redo intel_tile_height() as intel_tile_size() /
>     intel_tile_width()
>   drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size
>   drm/i915: Use intel_tile_{size,width,height}() in
>     intel_gen4_compute_page_offset()
>   drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/
>   drm/i915: Pass 90/270 vs. 0/180 rotation info for
>     intel_gen4_compute_page_offset()
>   drm/i915: Refactor intel_surf_alignment()
>   drm/i915: Support for extra alignment for tiled surfaces
>   drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
>   drm/i915: Set i915_ggtt_view_normal type explicitly
>   drm/i915: Move the partial and rotated view data into the same union
>   drm/i915: Don't treat differently sized rotated views as equal
>   drm/i915: Pass the dma_addr_t array as const to rotate_pages()
>   drm/i915: Pass stride to rotate_pages()
>   drm/i915: Pass rotation_info to intel_rotate_fb_obj_pages()
>   drm/i915: Make sure fb offset is (macro)pixel aligned
>   drm/i915: Don't leak framebuffer_references if drm_framebuffer_init()
>     fails
>   drm/i915: Pass drm_frambuffer to intel_compute_page_offset()
>   drm/i915: Rewrite fb rotation GTT handling
>   drm/i915: Don't pass pitch to intel_compute_page_offset()
> 
>  drivers/gpu/drm/i915/i915_gem.c      |  10 +-
>  drivers/gpu/drm/i915/i915_gem_gtt.c  |  88 ++--
>  drivers/gpu/drm/i915/i915_gem_gtt.h  |  27 +-
>  drivers/gpu/drm/i915/intel_display.c | 792 +++++++++++++++++++++++------------
>  drivers/gpu/drm/i915/intel_drv.h     |  46 +-
>  drivers/gpu/drm/i915/intel_fbdev.c   |   2 +-
>  drivers/gpu/drm/i915/intel_sprite.c  | 128 +++---
>  include/drm/drm_crtc.h               |  12 +
>  8 files changed, 681 insertions(+), 424 deletions(-)
> 
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-14 16:29 ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
@ 2015-10-15  9:08   ` Chris Wilson
  2015-10-15  9:36     ` Ville Syrjälä
  2015-10-15 11:10   ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() Tvrtko Ursulin
  2015-10-21 11:28   ` Daniel Vetter
  2 siblings, 1 reply; 76+ messages in thread
From: Chris Wilson @ 2015-10-15  9:08 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> rotation (to find the right GTT view for it), so no need to pass all
> kinds of plane stuff.

imho this is a mistep, I think using the plane-state to not only pass
the full description of the plane being bound (which may have additional
information like the need for fencing for fbc as well as alternative
views, i.e. it is a lot more versatile) but also allows us to track the
binding for the plane-state and tie the VMA to lifetime of the plane.

i.e. I think intel_pin_and_fence_fb_obj would be better described as
intel_plane_state_pin_vma (and correspondingly
intel_plane_state_unpin_vma).

Yes, intel_fbdev.c is a wart to any proposed interface.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-15  9:08   ` Chris Wilson
@ 2015-10-15  9:36     ` Ville Syrjälä
  2015-10-15 10:05       ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-15  9:36 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On Thu, Oct 15, 2015 at 10:08:53AM +0100, Chris Wilson wrote:
> On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> > rotation (to find the right GTT view for it), so no need to pass all
> > kinds of plane stuff.
> 
> imho this is a mistep, I think using the plane-state to not only pass
> the full description of the plane being bound (which may have additional
> information like the need for fencing for fbc as well as alternative
> views, i.e. it is a lot more versatile) but also allows us to track the
> binding for the plane-state and tie the VMA to lifetime of the plane.
> 
> i.e. I think intel_pin_and_fence_fb_obj would be better described as
> intel_plane_state_pin_vma (and correspondingly
> intel_plane_state_unpin_vma).
> 
> Yes, intel_fbdev.c is a wart to any proposed interface.

The current code is just too ugly to live IMO (due to fbdev, yes), so
I think we want this for now. We can always wrap it up in fancier
clothing for users that actually have a plane state once someone comes
up with some real code that needs it.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-15  9:36     ` Ville Syrjälä
@ 2015-10-15 10:05       ` Daniel Vetter
  2015-10-15 10:47         ` [PATCH] drm/i915: Split out aliasing-ppgtt from ggtt_bind_vma() Chris Wilson
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-15 10:05 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 12:36:43PM +0300, Ville Syrjälä wrote:
> On Thu, Oct 15, 2015 at 10:08:53AM +0100, Chris Wilson wrote:
> > On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> > > rotation (to find the right GTT view for it), so no need to pass all
> > > kinds of plane stuff.
> > 
> > imho this is a mistep, I think using the plane-state to not only pass
> > the full description of the plane being bound (which may have additional
> > information like the need for fencing for fbc as well as alternative
> > views, i.e. it is a lot more versatile) but also allows us to track the
> > binding for the plane-state and tie the VMA to lifetime of the plane.
> > 
> > i.e. I think intel_pin_and_fence_fb_obj would be better described as
> > intel_plane_state_pin_vma (and correspondingly
> > intel_plane_state_unpin_vma).
> > 
> > Yes, intel_fbdev.c is a wart to any proposed interface.
> 
> The current code is just too ugly to live IMO (due to fbdev, yes), so
> I think we want this for now. We can always wrap it up in fancier
> clothing for users that actually have a plane state once someone comes
> up with some real code that needs it.

To handle this we could make intel_pin_and_fence_fb return the vma for
callers to store in the plane state eventually, with errors encoded using
ERR_PTR. That way we can keep intel_fbdev.c as is and still store the vma
in the plane state.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH] drm/i915: Split out aliasing-ppgtt from ggtt_bind_vma()
  2015-10-15 10:05       ` Daniel Vetter
@ 2015-10-15 10:47         ` Chris Wilson
  0 siblings, 0 replies; 76+ messages in thread
From: Chris Wilson @ 2015-10-15 10:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

The presence of the aliasing-ppgtt (or rather its absence) causes some
confusion on old generations where we still pretend that there is a
difference between PIN_USER and PIN_GLOBAL even though we only have the
global GTT. The confusion has resulted in a bug where we do not mark the
vma as suitably bound for both types of access and so end up processing
the binding twice.

The double bind was accidentally introduced in

    commit 75d04a3773ecee617847de963ae4195d6aa74c28
    Author: Mika Kuoppala <mika.kuoppala@linux.intel.com>
    Date:   Tue Apr 28 17:56:17 2015 +0300

        drm/i915/gtt: Allocate va range only if vma is not bound

While at it implement an improved version suggested by Chris which
avoids the double-bind irrespective of what type of bind is done
first.

Note that this exact bug was already addressed in

commit d0e30adc42d979e4adc36b6c112b57337423b70c
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jul 29 20:02:48 2015 +0100

        drm/i915: Mark PIN_USER binding as GLOBAL_BIND without the aliasing ppgtt

but the problem is still that originally in

commit 0875546c5318c85c13d07014af5350e9000bc9e9
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Mon Apr 20 09:04:05 2015 -0700

        drm/i915: Fix up the vma aliasing ppgtt binding

if forgotten to take into account there case where we have a
GLOBAL_BIND before a LOCAL_BIND.

Here we separate out the binding into the global GTT for machines where
we have the aliasing-ppgtt and where we do not, so that we can perform
the fixup without further confusion.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 62 +++++++++++++++++++++++++++----------
 1 file changed, 45 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 0796aa06e9f5..81f4628ae0e6 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2493,7 +2493,6 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 			 enum i915_cache_level cache_level,
 			 u32 flags)
 {
-	struct drm_i915_private *dev_priv = to_i915(vma->vm->dev);
 	u32 pte_flags;
 	int ret;
 
@@ -2506,26 +2505,49 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 	if (vma->obj->gt_ro)
 		pte_flags |= PTE_READ_ONLY;
 
-	if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
+	vma->vm->insert_entries(vma->vm,
+				vma->ggtt_view.pages,
+				vma->node.start,
+				cache_level, pte_flags);
+
+	/* Note the inconsistency here is due to absence of the
+	 * aliasing ppgtt on gen5 and earlier. Though we always
+	 * request PIN_USER for execbuffer (translated to LOCAL_BIND),
+	 * without the appgtt, we cannot honour that request and so
+	 * must substitute it with a global binding. Since we do this
+	 * behind the upper layers back, we need to explicitly set
+	 * the bound flag ourselves.
+	 */
+	vma->bound |= GLOBAL_BIND | LOCAL_BIND;
+	return 0;
+}
+
+static int agtt_bind_vma(struct i915_vma *vma,
+			 enum i915_cache_level cache_level,
+			 u32 flags)
+{
+	u32 pte_flags;
+	int ret;
+
+	ret = i915_get_ggtt_vma_pages(vma);
+	if (ret)
+		return ret;
+
+	/* Currently applicable only to VLV */
+	pte_flags = 0;
+	if (vma->obj->gt_ro)
+		pte_flags |= PTE_READ_ONLY;
+
+	if (flags & GLOBAL_BIND) {
 		vma->vm->insert_entries(vma->vm,
 					vma->ggtt_view.pages,
 					vma->node.start,
 					cache_level, pte_flags);
-
-		/* Note the inconsistency here is due to absence of the
-		 * aliasing ppgtt on gen4 and earlier. Though we always
-		 * request PIN_USER for execbuffer (translated to LOCAL_BIND),
-		 * without the appgtt, we cannot honour that request and so
-		 * must substitute it with a global binding. Since we do this
-		 * behind the upper layers back, we need to explicitly set
-		 * the bound flag ourselves.
-		 */
-		vma->bound |= GLOBAL_BIND;
-
 	}
 
-	if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {
-		struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
+	if (flags & LOCAL_BIND) {
+		struct i915_hw_ppgtt *appgtt =
+			to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
 		appgtt->base.insert_entries(&appgtt->base,
 					    vma->ggtt_view.pages,
 					    vma->node.start,
@@ -2959,7 +2981,10 @@ static int gen8_gmch_probe(struct drm_device *dev,
 	dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range;
 	dev_priv->gtt.base.insert_page = gen8_ggtt_insert_page;
 	dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries;
-	dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
+	if (dev_priv->mm.aliasing_ppgtt)
+		dev_priv->gtt.base.bind_vma = agtt_bind_vma;
+	else
+		dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
 	dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
 
 	return ret;
@@ -3002,7 +3027,10 @@ static int gen6_gmch_probe(struct drm_device *dev,
 	dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range;
 	dev_priv->gtt.base.insert_page = gen6_ggtt_insert_page;
 	dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries;
-	dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
+	if (dev_priv->mm.aliasing_ppgtt)
+		dev_priv->gtt.base.bind_vma = agtt_bind_vma;
+	else
+		dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
 	dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
 
 	return ret;
-- 
2.6.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-14 16:29 ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
  2015-10-15  9:08   ` Chris Wilson
@ 2015-10-15 11:10   ` Tvrtko Ursulin
  2015-10-15 11:17     ` Ville Syrjälä
  2015-10-21 11:28   ` Daniel Vetter
  2 siblings, 1 reply; 76+ messages in thread
From: Tvrtko Ursulin @ 2015-10-15 11:10 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx


Hi,

On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> rotation (to find the right GTT view for it), so no need to pass all
> kinds of plane stuff.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++--------------------
>   drivers/gpu/drm/i915/intel_drv.h     |  5 ++---
>   drivers/gpu/drm/i915/intel_fbdev.c   |  2 +-
>   3 files changed, 20 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 85e1473..80e9f2e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2275,8 +2275,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
>   }
>
>   static int
> -intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> -			const struct drm_plane_state *plane_state)
> +intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> +			const struct drm_framebuffer *fb,
> +			unsigned int rotation)
>   {
>   	struct drm_i915_private *dev_priv = to_i915(fb->dev);
>   	struct intel_rotation_info *info = &view->rotation_info;
> @@ -2284,10 +2285,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>
>   	*view = i915_ggtt_view_normal;
>
> -	if (!plane_state)
> -		return 0;
> -
> -	if (!intel_rotation_90_or_270(plane_state->rotation))
> +	if (!intel_rotation_90_or_270(rotation))
>   		return 0;
>
>   	*view = i915_ggtt_view_rotated;
> @@ -2354,9 +2352,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
>   }
>
>   int
> -intel_pin_and_fence_fb_obj(struct drm_plane *plane,
> -			   struct drm_framebuffer *fb,
> -			   const struct drm_plane_state *plane_state,
> +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
> +			   unsigned int rotation,
>   			   struct intel_engine_cs *pipelined,
>   			   struct drm_i915_gem_request **pipelined_request)
>   {

It feels like you are losing the benefit of cleaning this up by having 
to pass in rotation anyway. So I think it makes more sense to keep 
passing in plane_state and only get rid of the plane. Or vice-versa, not 
really sure what is conceptually better. Possibly plane and then access 
the state from it.

Regards,

Tvrtko

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly
  2015-10-14 16:29 ` [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly ville.syrjala
@ 2015-10-15 11:15   ` Tvrtko Ursulin
  2015-10-15 12:01     ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Tvrtko Ursulin @ 2015-10-15 11:15 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx


Hi,

On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Just for clarity set the type for i915_ggtt_view_normal explicitly.
>
> While at it fix the indentation fail for i915_ggtt_view_rotated.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++--
>   1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index 620d57e..71acc71 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -95,9 +95,11 @@
>   static int
>   i915_get_ggtt_vma_pages(struct i915_vma *vma);
>
> -const struct i915_ggtt_view i915_ggtt_view_normal;
> +const struct i915_ggtt_view i915_ggtt_view_normal = {
> +	.type = I915_GGTT_VIEW_NORMAL,
> +};

AFAIR while this was developed Daniel was very keen on the normal view 
type being implicitly zero. Can't remember at this very moment if some 
of the current code actually depends on it though.

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-15 11:10   ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() Tvrtko Ursulin
@ 2015-10-15 11:17     ` Ville Syrjälä
  2015-10-15 11:30       ` Tvrtko Ursulin
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-15 11:17 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 12:10:32PM +0100, Tvrtko Ursulin wrote:
> 
> Hi,
> 
> On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> > rotation (to find the right GTT view for it), so no need to pass all
> > kinds of plane stuff.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++--------------------
> >   drivers/gpu/drm/i915/intel_drv.h     |  5 ++---
> >   drivers/gpu/drm/i915/intel_fbdev.c   |  2 +-
> >   3 files changed, 20 insertions(+), 26 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 85e1473..80e9f2e 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2275,8 +2275,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
> >   }
> >
> >   static int
> > -intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> > -			const struct drm_plane_state *plane_state)
> > +intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> > +			const struct drm_framebuffer *fb,
> > +			unsigned int rotation)
> >   {
> >   	struct drm_i915_private *dev_priv = to_i915(fb->dev);
> >   	struct intel_rotation_info *info = &view->rotation_info;
> > @@ -2284,10 +2285,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> >
> >   	*view = i915_ggtt_view_normal;
> >
> > -	if (!plane_state)
> > -		return 0;
> > -
> > -	if (!intel_rotation_90_or_270(plane_state->rotation))
> > +	if (!intel_rotation_90_or_270(rotation))
> >   		return 0;
> >
> >   	*view = i915_ggtt_view_rotated;
> > @@ -2354,9 +2352,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
> >   }
> >
> >   int
> > -intel_pin_and_fence_fb_obj(struct drm_plane *plane,
> > -			   struct drm_framebuffer *fb,
> > -			   const struct drm_plane_state *plane_state,
> > +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
> > +			   unsigned int rotation,
> >   			   struct intel_engine_cs *pipelined,
> >   			   struct drm_i915_gem_request **pipelined_request)
> >   {
> 
> It feels like you are losing the benefit of cleaning this up by having 
> to pass in rotation anyway. So I think it makes more sense to keep 
> passing in plane_state and only get rid of the plane. Or vice-versa, not 
> really sure what is conceptually better. Possibly plane and then access 
> the state from it.

The only thing we basically need is "which vma do we want". But just
passing rotation directly looks nicer I think. The benefit really is
eliminating the ugly 'if (!plane_state)' mess caused by intel_fbdev.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal
  2015-10-14 16:29 ` [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal ville.syrjala
@ 2015-10-15 11:18   ` Tvrtko Ursulin
  2015-10-15 12:02     ` Daniel Vetter
  2015-10-21 11:36   ` Daniel Vetter
  1 sibling, 1 reply; 76+ messages in thread
From: Tvrtko Ursulin @ 2015-10-15 11:18 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx


On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> In case we have multiple different rotated views into the same object,
> each one may need its own vma due to being of different sizes. So don't
> treat all rotated views as equal.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++
>   1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index caa182f..68de734 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -553,6 +553,8 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
>
>   	if (a->type != b->type)
>   		return false;
> +	if (a->type == I915_GGTT_VIEW_ROTATED)
> +		return !memcmp(&a->rotated, &b->rotated, sizeof(a->rotated));
>   	if (a->type == I915_GGTT_VIEW_PARTIAL)
>   		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
>   	return true;

This is where anonymous union causes problems since you have to build a 
switch statement before memcmp while the original goal was for memcmp to 
elegantly avoid that.

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-15 11:17     ` Ville Syrjälä
@ 2015-10-15 11:30       ` Tvrtko Ursulin
  2015-10-15 12:11         ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Tvrtko Ursulin @ 2015-10-15 11:30 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx


On 15/10/15 12:17, Ville Syrjälä wrote:
> On Thu, Oct 15, 2015 at 12:10:32PM +0100, Tvrtko Ursulin wrote:
>>
>> Hi,
>>
>> On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
>>> rotation (to find the right GTT view for it), so no need to pass all
>>> kinds of plane stuff.
>>>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++--------------------
>>>    drivers/gpu/drm/i915/intel_drv.h     |  5 ++---
>>>    drivers/gpu/drm/i915/intel_fbdev.c   |  2 +-
>>>    3 files changed, 20 insertions(+), 26 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 85e1473..80e9f2e 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -2275,8 +2275,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
>>>    }
>>>
>>>    static int
>>> -intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>>> -			const struct drm_plane_state *plane_state)
>>> +intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
>>> +			const struct drm_framebuffer *fb,
>>> +			unsigned int rotation)
>>>    {
>>>    	struct drm_i915_private *dev_priv = to_i915(fb->dev);
>>>    	struct intel_rotation_info *info = &view->rotation_info;
>>> @@ -2284,10 +2285,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>>>
>>>    	*view = i915_ggtt_view_normal;
>>>
>>> -	if (!plane_state)
>>> -		return 0;
>>> -
>>> -	if (!intel_rotation_90_or_270(plane_state->rotation))
>>> +	if (!intel_rotation_90_or_270(rotation))
>>>    		return 0;
>>>
>>>    	*view = i915_ggtt_view_rotated;
>>> @@ -2354,9 +2352,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
>>>    }
>>>
>>>    int
>>> -intel_pin_and_fence_fb_obj(struct drm_plane *plane,
>>> -			   struct drm_framebuffer *fb,
>>> -			   const struct drm_plane_state *plane_state,
>>> +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
>>> +			   unsigned int rotation,
>>>    			   struct intel_engine_cs *pipelined,
>>>    			   struct drm_i915_gem_request **pipelined_request)
>>>    {
>>
>> It feels like you are losing the benefit of cleaning this up by having
>> to pass in rotation anyway. So I think it makes more sense to keep
>> passing in plane_state and only get rid of the plane. Or vice-versa, not
>> really sure what is conceptually better. Possibly plane and then access
>> the state from it.
>
> The only thing we basically need is "which vma do we want". But just
> passing rotation directly looks nicer I think. The benefit really is
> eliminating the ugly 'if (!plane_state)' mess caused by intel_fbdev.

We'll have to disagree there then because I find it really inelegant to 
express the knowledge of what exact information is needed when preparing 
the frame buffer for display into the function parameters.

It is conceptually much more elegant to say "this fb for this plane - do 
what is right".

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly
  2015-10-15 11:15   ` Tvrtko Ursulin
@ 2015-10-15 12:01     ` Daniel Vetter
  2015-10-21 11:28       ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-15 12:01 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 12:15:21PM +0100, Tvrtko Ursulin wrote:
> 
> Hi,
> 
> On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> >Just for clarity set the type for i915_ggtt_view_normal explicitly.
> >
> >While at it fix the indentation fail for i915_ggtt_view_rotated.
> >
> >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >---
> >  drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> >index 620d57e..71acc71 100644
> >--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> >+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> >@@ -95,9 +95,11 @@
> >  static int
> >  i915_get_ggtt_vma_pages(struct i915_vma *vma);
> >
> >-const struct i915_ggtt_view i915_ggtt_view_normal;
> >+const struct i915_ggtt_view i915_ggtt_view_normal = {
> >+	.type = I915_GGTT_VIEW_NORMAL,
> >+};
> 
> AFAIR while this was developed Daniel was very keen on the normal view type
> being implicitly zero. Can't remember at this very moment if some of the
> current code actually depends on it though.

We kzalloc vmas, which means any view in there is normal by default. Still
very much keen on that ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal
  2015-10-15 11:18   ` Tvrtko Ursulin
@ 2015-10-15 12:02     ` Daniel Vetter
  2015-10-15 12:06       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-15 12:02 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 12:18:41PM +0100, Tvrtko Ursulin wrote:
> 
> On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> >In case we have multiple different rotated views into the same object,
> >each one may need its own vma due to being of different sizes. So don't
> >treat all rotated views as equal.
> >
> >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >---
> >  drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> >diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> >index caa182f..68de734 100644
> >--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> >+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> >@@ -553,6 +553,8 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
> >
> >  	if (a->type != b->type)
> >  		return false;
> >+	if (a->type == I915_GGTT_VIEW_ROTATED)
> >+		return !memcmp(&a->rotated, &b->rotated, sizeof(a->rotated));
> >  	if (a->type == I915_GGTT_VIEW_PARTIAL)
> >  		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
> >  	return true;
> 
> This is where anonymous union causes problems since you have to build a
> switch statement before memcmp while the original goal was for memcmp to
> elegantly avoid that.

Yup, mentioned the same on irc. I much prefer we do the memcmp on type !=
NORMAL, to avoid mistakes when adding more views in the future.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal
  2015-10-15 12:02     ` Daniel Vetter
@ 2015-10-15 12:06       ` Ville Syrjälä
  2015-10-15 12:24         ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-15 12:06 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 02:02:24PM +0200, Daniel Vetter wrote:
> On Thu, Oct 15, 2015 at 12:18:41PM +0100, Tvrtko Ursulin wrote:
> > 
> > On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> > >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > >In case we have multiple different rotated views into the same object,
> > >each one may need its own vma due to being of different sizes. So don't
> > >treat all rotated views as equal.
> > >
> > >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >---
> > >  drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > >diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > >index caa182f..68de734 100644
> > >--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> > >+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > >@@ -553,6 +553,8 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
> > >
> > >  	if (a->type != b->type)
> > >  		return false;
> > >+	if (a->type == I915_GGTT_VIEW_ROTATED)
> > >+		return !memcmp(&a->rotated, &b->rotated, sizeof(a->rotated));
> > >  	if (a->type == I915_GGTT_VIEW_PARTIAL)
> > >  		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
> > >  	return true;
> > 
> > This is where anonymous union causes problems since you have to build a
> > switch statement before memcmp while the original goal was for memcmp to
> > elegantly avoid that.
> 
> Yup, mentioned the same on irc. I much prefer we do the memcmp on type !=
> NORMAL, to avoid mistakes when adding more views in the future.

I just dislike the .partial. extra stuff all over. But whatever, it's a
minor detail in my book. We can go with the non-anon union if people
prefer that.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-15 11:30       ` Tvrtko Ursulin
@ 2015-10-15 12:11         ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-15 12:11 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 12:30:44PM +0100, Tvrtko Ursulin wrote:
> 
> On 15/10/15 12:17, Ville Syrjälä wrote:
> > On Thu, Oct 15, 2015 at 12:10:32PM +0100, Tvrtko Ursulin wrote:
> >>
> >> Hi,
> >>
> >> On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> >>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>
> >>> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> >>> rotation (to find the right GTT view for it), so no need to pass all
> >>> kinds of plane stuff.
> >>>
> >>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>> ---
> >>>    drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++--------------------
> >>>    drivers/gpu/drm/i915/intel_drv.h     |  5 ++---
> >>>    drivers/gpu/drm/i915/intel_fbdev.c   |  2 +-
> >>>    3 files changed, 20 insertions(+), 26 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >>> index 85e1473..80e9f2e 100644
> >>> --- a/drivers/gpu/drm/i915/intel_display.c
> >>> +++ b/drivers/gpu/drm/i915/intel_display.c
> >>> @@ -2275,8 +2275,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
> >>>    }
> >>>
> >>>    static int
> >>> -intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> >>> -			const struct drm_plane_state *plane_state)
> >>> +intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> >>> +			const struct drm_framebuffer *fb,
> >>> +			unsigned int rotation)
> >>>    {
> >>>    	struct drm_i915_private *dev_priv = to_i915(fb->dev);
> >>>    	struct intel_rotation_info *info = &view->rotation_info;
> >>> @@ -2284,10 +2285,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> >>>
> >>>    	*view = i915_ggtt_view_normal;
> >>>
> >>> -	if (!plane_state)
> >>> -		return 0;
> >>> -
> >>> -	if (!intel_rotation_90_or_270(plane_state->rotation))
> >>> +	if (!intel_rotation_90_or_270(rotation))
> >>>    		return 0;
> >>>
> >>>    	*view = i915_ggtt_view_rotated;
> >>> @@ -2354,9 +2352,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
> >>>    }
> >>>
> >>>    int
> >>> -intel_pin_and_fence_fb_obj(struct drm_plane *plane,
> >>> -			   struct drm_framebuffer *fb,
> >>> -			   const struct drm_plane_state *plane_state,
> >>> +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
> >>> +			   unsigned int rotation,
> >>>    			   struct intel_engine_cs *pipelined,
> >>>    			   struct drm_i915_gem_request **pipelined_request)
> >>>    {
> >>
> >> It feels like you are losing the benefit of cleaning this up by having
> >> to pass in rotation anyway. So I think it makes more sense to keep
> >> passing in plane_state and only get rid of the plane. Or vice-versa, not
> >> really sure what is conceptually better. Possibly plane and then access
> >> the state from it.
> >
> > The only thing we basically need is "which vma do we want". But just
> > passing rotation directly looks nicer I think. The benefit really is
> > eliminating the ugly 'if (!plane_state)' mess caused by intel_fbdev.
> 
> We'll have to disagree there then because I find it really inelegant to 
> express the knowledge of what exact information is needed when preparing 
> the frame buffer for display into the function parameters.
> 
> It is conceptually much more elegant to say "this fb for this plane - do 
> what is right".

Only if the function is actually used for that. With fbdev it's not.
Chris did sell the "vma in plane state" idea to me last night on irc, so
when we get that we probably want a function that accepts the plane
state. But that can basically just wrap the current thing, which means
fbdev can keep using the lower level function that doesn't need the
plane state.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal
  2015-10-15 12:06       ` Ville Syrjälä
@ 2015-10-15 12:24         ` Daniel Vetter
  2015-10-21 13:06           ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-15 12:24 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 03:06:11PM +0300, Ville Syrjälä wrote:
> On Thu, Oct 15, 2015 at 02:02:24PM +0200, Daniel Vetter wrote:
> > On Thu, Oct 15, 2015 at 12:18:41PM +0100, Tvrtko Ursulin wrote:
> > > 
> > > On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> > > >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > >
> > > >In case we have multiple different rotated views into the same object,
> > > >each one may need its own vma due to being of different sizes. So don't
> > > >treat all rotated views as equal.
> > > >
> > > >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > >---
> > > >  drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++
> > > >  1 file changed, 2 insertions(+)
> > > >
> > > >diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > > >index caa182f..68de734 100644
> > > >--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> > > >+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > > >@@ -553,6 +553,8 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
> > > >
> > > >  	if (a->type != b->type)
> > > >  		return false;
> > > >+	if (a->type == I915_GGTT_VIEW_ROTATED)
> > > >+		return !memcmp(&a->rotated, &b->rotated, sizeof(a->rotated));
> > > >  	if (a->type == I915_GGTT_VIEW_PARTIAL)
> > > >  		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
> > > >  	return true;
> > > 
> > > This is where anonymous union causes problems since you have to build a
> > > switch statement before memcmp while the original goal was for memcmp to
> > > elegantly avoid that.
> > 
> > Yup, mentioned the same on irc. I much prefer we do the memcmp on type !=
> > NORMAL, to avoid mistakes when adding more views in the future.
> 
> I just dislike the .partial. extra stuff all over. But whatever, it's a
> minor detail in my book. We can go with the non-anon union if people
> prefer that.

Here it would be
	if (a->type != NORMA))
		return !memcmp(&a->params, &b->params);

Seems at least in this case cleaner. But yet everywhere else you'll get a
params., but that can be alleviated a bit with local variables.
-Daniel
> 
> -- 
> Ville Syrjälä
> Intel OTC

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH v2 21/22] drm/i915: Rewrite fb rotation GTT handling
  2015-10-14 16:29 ` [PATCH 21/22] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
@ 2015-10-15 17:59   ` ville.syrjala
  2015-10-21 12:01     ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: ville.syrjala @ 2015-10-15 17:59 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Redo the fb rotation handling in order to:
- eliminate the NV12 special casing
- handle fb->offsets[] properly
- make the rotation handling reasier for the plane code

To achieve these goals we reduce intel_rotation_info to only contain
(for each plane) the rotated view width,height,stride in tile units,
and the page offset into the object where the plane starts. Each plane
is handled exactly the same way, no special casing for NV12 or other
formats. We then store the computed rotation_info under
intel_framebuffer so that we don't have to recompute it again.

To handle fb->offsets[] we treat them as a linear offsets and convert
them to x/y offsets from the start of the relevant GTT mapping (either
normal or rotated). We store the x/y offsets under intel_framebuffer,
and for some extra convenience we also store the rotated pitch (ie.
tile aligned plane height). So for each plane we have the normal
x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
pitch is available already in fb->pitches[].

While we're gathering up all that extra information, we can also easily
compute the storage requirements for the framebuffer, so that we can
check that the object is big enough to hold it.

When it comes time to deal with the plane source coordinates, we first
rotate the clipped src coordinates to match the relevant GTT view
orientation, then add to them the fb x/y offsets. Next we compute
the aligned surface page offset, and as a result we're left with some
residual x/y offsets. Finally, if required by the hardware, we convert
the remaining x/y offsets into a linear offset.

For gen2/3 we simply skip computing the final page offset, and just
convert the src+fb x/y offsets directly into a linear offset since
that's what the hardware wants.

After this all platforms, incluing SKL+, compute these things in exactly
the same way (excluding alignemnt differences).

v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
    plane src coordinates
    Drop some spurious changes that got left behind during development

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c  |  66 ++----
 drivers/gpu/drm/i915/i915_gem_gtt.h  |  14 +-
 drivers/gpu/drm/i915/intel_display.c | 448 ++++++++++++++++++++++++-----------
 drivers/gpu/drm/i915/intel_drv.h     |  32 ++-
 drivers/gpu/drm/i915/intel_sprite.c  | 102 ++++----
 5 files changed, 402 insertions(+), 260 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index bb95b86..98aee6c 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3255,11 +3255,6 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
 	unsigned int column, row;
 	unsigned int src_idx;
 
-	if (!sg) {
-		st->nents = 0;
-		sg = st->sgl;
-	}
-
 	for (column = 0; column < width; column++) {
 		src_idx = stride * (height - 1) + column;
 		for (row = 0; row < height; row++) {
@@ -3280,16 +3275,14 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
 }
 
 static struct sg_table *
-intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
+intel_rotate_fb_obj_pages(const struct intel_rotation_info *info,
 			  struct drm_i915_gem_object *obj)
 {
-	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
-	unsigned int size_pages_uv;
+	unsigned int size = intel_rotation_info_size(info);
 	struct sg_page_iter sg_iter;
 	unsigned long i;
 	dma_addr_t *page_addr_list;
 	struct sg_table *st;
-	unsigned int uv_start_page;
 	struct scatterlist *sg;
 	int ret = -ENOMEM;
 
@@ -3299,57 +3292,32 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
 	if (!page_addr_list)
 		return ERR_PTR(ret);
 
-	/* Account for UV plane with NV12. */
-	if (rot_info->pixel_format == DRM_FORMAT_NV12)
-		size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
-	else
-		size_pages_uv = 0;
-
 	/* Allocate target SG list. */
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st)
 		goto err_st_alloc;
 
-	ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
+	ret = sg_alloc_table(st, size, GFP_KERNEL);
 	if (ret)
 		goto err_sg_alloc;
 
 	/* Populate source page list from the object. */
 	i = 0;
 	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
-		page_addr_list[i] = sg_page_iter_dma_address(&sg_iter);
-		i++;
+		page_addr_list[i++] = sg_page_iter_dma_address(&sg_iter);
 	}
 
-	/* Rotate the pages. */
-	sg = rotate_pages(page_addr_list, 0,
-		     rot_info->width_pages, rot_info->height_pages,
-		     rot_info->width_pages,
-		     st, NULL);
+	st->nents = 0;
+	sg = st->sgl;
 
-	/* Append the UV plane if NV12. */
-	if (rot_info->pixel_format == DRM_FORMAT_NV12) {
-		uv_start_page = size_pages;
-
-		/* Check for tile-row un-alignment. */
-		if (offset_in_page(rot_info->uv_offset))
-			uv_start_page--;
-
-		rot_info->uv_start_page = uv_start_page;
-
-		rotate_pages(page_addr_list, uv_start_page,
-			     rot_info->width_pages_uv,
-			     rot_info->height_pages_uv,
-			     rot_info->width_pages_uv,
-			     st, sg);
+	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++) {
+		sg = rotate_pages(page_addr_list, info->plane[i].offset,
+				  info->plane[i].width, info->plane[i].height,
+				  info->plane[i].stride, st, sg);
 	}
 
-	DRM_DEBUG_KMS(
-		      "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
-		      obj->base.size, rot_info->pitch, rot_info->height,
-		      rot_info->pixel_format, rot_info->width_pages,
-		      rot_info->height_pages, size_pages + size_pages_uv,
-		      size_pages);
+	DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages)\n",
+		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
 
 	drm_free_large(page_addr_list);
 
@@ -3360,12 +3328,8 @@ err_sg_alloc:
 err_st_alloc:
 	drm_free_large(page_addr_list);
 
-	DRM_DEBUG_KMS(
-		      "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
-		      obj->base.size, ret, rot_info->pitch, rot_info->height,
-		      rot_info->pixel_format, rot_info->width_pages,
-		      rot_info->height_pages, size_pages + size_pages_uv,
-		      size_pages);
+	DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
+		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
 	return ERR_PTR(ret);
 }
 
@@ -3516,7 +3480,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
 	if (view->type == I915_GGTT_VIEW_NORMAL) {
 		return obj->base.size;
 	} else if (view->type == I915_GGTT_VIEW_ROTATED) {
-		return view->rotated.size;
+		return intel_rotation_info_size(&view->rotated) << PAGE_SHIFT;
 	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
 		return view->partial.size << PAGE_SHIFT;
 	} else {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 68de734..ea28f7d 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -136,16 +136,10 @@ enum i915_ggtt_view_type {
 };
 
 struct intel_rotation_info {
-	unsigned int height;
-	unsigned int pitch;
-	unsigned int uv_offset;
-	uint32_t pixel_format;
-	uint64_t fb_modifier;
-	unsigned int width_pages, height_pages;
-	uint64_t size;
-	unsigned int width_pages_uv, height_pages_uv;
-	uint64_t size_uv;
-	unsigned int uv_start_page;
+	struct {
+		/* tiles */
+		unsigned int width, height, stride, offset;
+	} plane[2];
 };
 
 struct i915_ggtt_view {
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 028dc4a..0dcb710 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2274,49 +2274,28 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
 	return ALIGN(height, tile_height);
 }
 
-static int
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *info)
+{
+	unsigned int size = 0;
+	int i;
+
+	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++)
+		size += info->plane[i].width * info->plane[i].height;
+
+	return size;
+}
+
+static void
 intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
 			const struct drm_framebuffer *fb,
 			unsigned int rotation)
 {
-	struct drm_i915_private *dev_priv = to_i915(fb->dev);
-	struct intel_rotation_info *info = &view->rotated;
-	unsigned int tile_size, tile_width, tile_height, cpp;
-
-	*view = i915_ggtt_view_normal;
-
-	if (!intel_rotation_90_or_270(rotation))
-		return 0;
-
-	*view = i915_ggtt_view_rotated;
-
-	info->height = fb->height;
-	info->pixel_format = fb->pixel_format;
-	info->pitch = fb->pitches[0];
-	info->uv_offset = fb->offsets[1];
-	info->fb_modifier = fb->modifier[0];
-
-	tile_size = intel_tile_size(dev_priv);
-
-	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-	tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
-	tile_height = tile_size / tile_width;
-
-	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
-	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
-	info->size = info->width_pages * info->height_pages * tile_size;
-
-	if (info->pixel_format == DRM_FORMAT_NV12) {
-		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
-		tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
-		tile_height = tile_size / tile_width;
-
-		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
-		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
-		info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
+	if (intel_rotation_90_or_270(rotation)) {
+		*view = i915_ggtt_view_rotated;
+		view->rotated = to_intel_framebuffer(fb)->info;
+	} else {
+		*view = i915_ggtt_view_normal;
 	}
-
-	return 0;
 }
 
 static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
@@ -2368,9 +2347,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 
 	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
 
-	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
-	if (ret)
-		return ret;
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
 	/* Note that the w/a also requires 64 PTE of padding following the
 	 * bo. We currently fill all unused PTE with the shadow page and so
@@ -2433,18 +2410,31 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation
 {
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct i915_ggtt_view view;
-	int ret;
 
 	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
 
-	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
-	WARN_ONCE(ret, "Couldn't get view from plane state!");
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
 	i915_gem_object_unpin_fence(obj);
 	i915_gem_object_unpin_from_display_plane(obj, &view);
 }
 
 /*
+ * Convert the x/y offsets into a linear offset.
+ * Only valid with 0/180 degree rotation, which is fine since linear
+ * offset is only used with linear buffers on pre-hsw and tiled buffers
+ * with gen2/3, and 90/270 degree rotations isn't supported on any of them.
+ */
+unsigned int intel_fb_xy_to_linear(int x, int y,
+				   const struct drm_framebuffer *fb, int plane)
+{
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+	unsigned int pitch = fb->pitches[plane];
+
+	return y * pitch + x * cpp;
+}
+
+/*
  * Return the tile dimensions in pixel units matching
  * the specified rotation angle.
  */
@@ -2475,6 +2465,55 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
 }
 
 /*
+ * Add the x/y offsets derived from fb->offsets[] to the user
+ * specified plane src x/y offsets. The resulting x/y offsets
+ * specify the start of scanout from the beginning of the gtt mapping.
+ */
+void intel_add_fb_offsets(int *x, int *y,
+			  const struct drm_framebuffer *fb, int plane,
+			  unsigned int rotation)
+
+{
+	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+	const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+	unsigned int pitch;
+
+	if (intel_rotation_90_or_270(rotation)) {
+		pitch = intel_fb->plane[plane].rotated.pitch;
+
+		*x += intel_fb->plane[plane].rotated.x;
+		*y += intel_fb->plane[plane].rotated.y;
+	} else {
+		pitch = fb->pitches[plane];
+
+		*x += intel_fb->plane[plane].normal.x;
+		*y += intel_fb->plane[plane].normal.y;
+	}
+
+	/* minimize x */
+	if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
+		unsigned int tile_size, tile_width, tile_height;
+
+		tile_size = intel_tile_size(dev_priv);
+		tile_width = intel_tile_width(dev_priv, fb->modifier[plane], cpp);
+		tile_height = tile_size / tile_width;
+
+		intel_rotate_tile_dims(&tile_width, &tile_height,
+				       &pitch, cpp, rotation);
+
+		*y += *x / pitch * tile_height;
+		*x  = *x % pitch;
+	} else {
+		/* in pixels */
+		pitch /= cpp;
+
+		*y += *x / pitch;
+		*x  = *x % pitch;
+	}
+}
+
+/*
  * Adjust the page offset by moving the difference into
  * the x/y offsets.
  *
@@ -2514,20 +2553,23 @@ static void intel_adjust_page_offset(int *x, int *y,
  * In the 90/270 rotated case, x and y are assumed
  * to be already rotated to match the rotated GTT view, and
  * pitch is the tile_height aligned framebuffer height.
+ *
+ * This function is used when computing the derived information
+ * under intel_framebuffer, so using any of that information
+ * here is not allowed. Anything under drm_framebuffer can be
+ * used. This is why the user has to pass in the pitch since it
+ * is specified in the rotated orientation.
  */
-unsigned long intel_compute_page_offset(int *x, int *y,
-					const struct drm_framebuffer *fb, int plane,
-					unsigned int pitch,
-					unsigned int rotation)
+static unsigned int _intel_compute_page_offset(const struct drm_i915_private *dev_priv,
+					       int *x, int *y,
+					       const struct drm_framebuffer *fb, int plane,
+					       unsigned int pitch,
+					       unsigned int rotation,
+					       unsigned int alignment)
 {
-	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
 	uint64_t fb_modifier = fb->modifier[plane];
 	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
-	unsigned int offset, alignment;
-
-	alignment = intel_surf_alignment(dev_priv, fb_modifier);
-	if (alignment)
-		alignment--;
+	unsigned int offset;
 
 	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_size, tile_width, tile_height;
@@ -2560,6 +2602,145 @@ unsigned long intel_compute_page_offset(int *x, int *y,
 	return offset & ~alignment;
 }
 
+unsigned int intel_compute_page_offset(int *x, int *y,
+				       const struct drm_framebuffer *fb, int plane,
+				       unsigned int pitch,
+				       unsigned int rotation)
+{
+	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+	unsigned int alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
+
+	return _intel_compute_page_offset(dev_priv, x, y, fb, plane, pitch,
+					  rotation, alignment ? (alignment - 1) : 0);
+}
+
+/* Convert the fb->offset[] linear offset into x/y offsets */
+static void intel_fb_offset_to_xy(int *x, int *y,
+				  const struct drm_framebuffer *fb, int plane)
+{
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+	unsigned int pitch = fb->pitches[plane];
+	unsigned int linear_offset = fb->offsets[plane];
+
+	*y = linear_offset / pitch;
+	*x = linear_offset % pitch / cpp;
+}
+
+static int
+intel_fill_fb_info(struct drm_i915_private *dev_priv,
+		   struct drm_framebuffer *fb)
+{
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+	struct intel_rotation_info *info = &intel_fb->info;
+	unsigned int tile_size;
+	unsigned int gtt_offset_rotated = 0;
+	unsigned int max_size = 0;
+	uint32_t format = fb->pixel_format;
+	int i, num_planes = drm_format_num_planes(format);
+
+	tile_size = intel_tile_size(dev_priv);
+
+	for (i = 0; i < num_planes; i++) {
+		unsigned int width, height;
+		unsigned int cpp, offset, size;
+		int x, y;
+
+		cpp = drm_format_plane_cpp(format, i);
+		width = drm_format_plane_width(fb->width, format, i);
+		height = drm_format_plane_height(fb->height, format, i);
+
+		intel_fb_offset_to_xy(&x, &y, fb, i);
+
+		/*
+		 * First pixel of the framebuffer from
+		 * the start of the normal gtt mapping.
+		 */
+		intel_fb->plane[i].normal.x = x;
+		intel_fb->plane[i].normal.y = y;
+
+		offset = _intel_compute_page_offset(dev_priv, &x, &y,
+						    fb, 0, fb->pitches[i],
+						    BIT(DRM_ROTATE_0),
+						    tile_size);
+		offset /= tile_size;
+		DRM_DEBUG("page offset %u pages\n", offset);
+
+		if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
+			unsigned int tile_width, tile_height;
+			unsigned int pitch;
+			struct drm_rect r;
+
+			tile_width = intel_tile_width(dev_priv, fb->modifier[i], cpp);
+			tile_height = tile_size / tile_width;
+
+			info->plane[i].offset = offset;
+			info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width);
+			info->plane[i].width = DIV_ROUND_UP((x + width) * cpp, tile_width);
+			info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
+
+
+			intel_fb->plane[i].rotated.pitch =
+				info->plane[i].height * tile_height;
+
+			/* how many tiles does this plane need */
+			size = info->plane[i].stride * info->plane[i].height;
+			/*
+			 * If the plane isn't horizontally tile aligned,
+			 * we need one more tile.
+			 */
+			if (x != 0)
+				size++;
+
+			pitch = intel_fb->plane[i].rotated.pitch;
+
+			/* rotate the x/y offsets to match the GTT view */
+			r.x1 = x;
+			r.y1 = y;
+			r.x2 = x + width;
+			r.y2 = y + height;
+			drm_rect_rotate(&r, width, pitch, BIT(DRM_ROTATE_270));
+			x = r.x1;
+			y = r.y1;
+
+			intel_rotate_tile_dims(&tile_width, &tile_height, &pitch,
+					       cpp, BIT(DRM_ROTATE_270));
+
+			/*
+			 * We only keep the x/y offsets, so push all of the
+			 * gtt offset into the x/y offsets.
+			 */
+			intel_adjust_page_offset(&x, &y, tile_width, tile_height,
+						 tile_size, pitch,
+						 gtt_offset_rotated * tile_size, 0);
+
+			gtt_offset_rotated += info->plane[i].width * info->plane[i].height;
+
+			/*
+			 * First pixel of the framebuffer from
+			 * the start of the rotated gtt mapping.
+			 */
+			intel_fb->plane[i].rotated.x = x;
+			intel_fb->plane[i].rotated.y = y;
+		} else {
+			size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
+					    x * cpp, tile_size);
+		}
+		DRM_DEBUG("%d offset %u, size %u, stride %u, height %u\n",
+			  i, offset, size, info->plane[i].stride, info->plane[i].height);
+
+		/* how many tiles in total needed in the bo */
+		max_size = max(max_size, offset + size);
+	}
+
+	if (max_size * tile_size > to_intel_framebuffer(fb)->obj->base.size) {
+		DRM_DEBUG("fb too big for bo (need %u bytes, have %zu bytes)\n",
+			  max_size * tile_size, to_intel_framebuffer(fb)->obj->base.size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int i9xx_format_to_fourcc(int format)
 {
 	switch (format) {
@@ -2761,7 +2942,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
 	unsigned int rotation;
-	unsigned long linear_offset;
+	unsigned int linear_offset;
 	u32 dspcntr;
 	u32 reg = DSPCNTR(plane);
 	int pixel_size;
@@ -2839,30 +3020,25 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	if (IS_G4X(dev))
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_INFO(dev)->gen >= 4)
 		intel_crtc->dspaddr_offset =
 			intel_compute_page_offset(&x, &y, fb, 0,
 						  fb->pitches[0], rotation);
-		linear_offset -= intel_crtc->dspaddr_offset;
-	} else {
-		intel_crtc->dspaddr_offset = linear_offset;
-	}
 
 	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
 
 		x += (intel_crtc->config->pipe_src_w - 1);
 		y += (intel_crtc->config->pipe_src_h - 1);
-
-		/* Finding the last pixel of the last line of the display
-		data and adding to linear_offset*/
-		linear_offset +=
-			(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
-			(intel_crtc->config->pipe_src_w - 1) * pixel_size;
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
+	if (INTEL_INFO(dev)->gen < 4)
+		intel_crtc->dspaddr_offset = linear_offset;
+
 	intel_crtc->adjusted_x = x;
 	intel_crtc->adjusted_y = y;
 
@@ -2871,7 +3047,8 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	if (INTEL_INFO(dev)->gen >= 4) {
 		I915_WRITE(DSPSURF(plane),
-			   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+			   intel_surf_gtt_offset(fb, 0, rotation) +
+			   intel_crtc->dspaddr_offset);
 		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
 		I915_WRITE(DSPLINOFF(plane), linear_offset);
 	} else
@@ -2891,7 +3068,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	struct drm_i915_gem_object *obj;
 	int plane = intel_crtc->plane;
 	unsigned int rotation;
-	unsigned long linear_offset;
+	unsigned int linear_offset;
 	u32 dspcntr;
 	u32 reg = DSPCNTR(plane);
 	int pixel_size;
@@ -2946,26 +3123,22 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 	if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	intel_crtc->dspaddr_offset =
 		intel_compute_page_offset(&x, &y, fb, 0,
 					  fb->pitches[0], rotation);
-	linear_offset -= intel_crtc->dspaddr_offset;
+
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
 
 		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
 			x += (intel_crtc->config->pipe_src_w - 1);
 			y += (intel_crtc->config->pipe_src_h - 1);
-
-			/* Finding the last pixel of the last line of the display
-			data and adding to linear_offset*/
-			linear_offset +=
-				(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
-				(intel_crtc->config->pipe_src_w - 1) * pixel_size;
 		}
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	intel_crtc->adjusted_x = x;
 	intel_crtc->adjusted_y = y;
 
@@ -2973,7 +3146,8 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	I915_WRITE(DSPSURF(plane),
-		   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+		   intel_surf_gtt_offset(fb, 0, rotation) +
+		   intel_crtc->dspaddr_offset);
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
 		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
 	} else {
@@ -3000,30 +3174,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
 	}
 }
 
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
-				     struct drm_i915_gem_object *obj,
-				     unsigned int plane)
+unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
+				   unsigned int rotation)
 {
-	const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
-	struct i915_vma *vma;
-	unsigned char *offset;
+	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	struct i915_ggtt_view view;
 
-	if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
-		view = &i915_ggtt_view_rotated;
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
-	vma = i915_gem_obj_to_ggtt_view(obj, view);
-	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
-		view->type))
-		return -1;
-
-	offset = (unsigned char *)vma->node.start;
-
-	if (plane == 1) {
-		offset += vma->ggtt_view.rotated.uv_start_page *
-			  PAGE_SIZE;
-	}
-
-	return (unsigned long)offset;
+	return i915_gem_obj_ggtt_offset_view(obj, &view);
 }
 
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3142,18 +3301,16 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_plane *plane = crtc->primary;
+	struct intel_framebuffer *intel_fb;
 	bool visible = to_intel_plane_state(plane->state)->visible;
-	struct drm_i915_gem_object *obj;
 	int pipe = intel_crtc->pipe;
 	u32 plane_ctl, stride_div, stride;
-	u32 tile_height, plane_offset, plane_size;
 	unsigned int rotation;
-	int x_offset, y_offset;
 	unsigned long surf_addr;
 	struct intel_crtc_state *crtc_state = intel_crtc->config;
 	struct intel_plane_state *plane_state;
-	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
-	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
+	int src_w, src_h;
+	int dst_x, dst_y, dst_w, dst_h;
 	int scaler_id = -1;
 	int pixel_size;
 
@@ -3166,6 +3323,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		return;
 	}
 
+	intel_fb = to_intel_framebuffer(fb);
 	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	plane_ctl = PLANE_CTL_ENABLE |
@@ -3179,16 +3337,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	rotation = plane->state->rotation;
 	plane_ctl |= skl_plane_ctl_rotation(rotation);
 
-	obj = intel_fb_obj(fb);
-	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
-					       fb->pixel_format);
-	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
-
-	WARN_ON(drm_rect_width(&plane_state->src) == 0);
-
 	scaler_id = plane_state->scaler_id;
-	src_x = plane_state->src.x1 >> 16;
-	src_y = plane_state->src.y1 >> 16;
 	src_w = drm_rect_width(&plane_state->src) >> 16;
 	src_h = drm_rect_height(&plane_state->src) >> 16;
 	dst_x = plane_state->dst.x1;
@@ -3196,31 +3345,48 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	dst_w = drm_rect_width(&plane_state->dst);
 	dst_h = drm_rect_height(&plane_state->dst);
 
-	WARN_ON(x != src_x || y != src_y);
-
 	if (intel_rotation_90_or_270(rotation)) {
-		/* stride = Surface height in tiles */
-		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
-						pixel_size);
-		stride = DIV_ROUND_UP(fb->height, tile_height);
-		x_offset = stride * tile_height - y - src_h;
-		y_offset = x;
-		plane_size = (src_w - 1) << 16 | (src_h - 1);
+		struct drm_rect r = {
+			.x1 = x,
+			.x2 = x + src_w,
+			.y1 = y,
+			.y2 = y + src_h,
+		};
+
+		/* Rotate src coordinates to match rotated GTT view */
+		drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
+
+		x = r.x1;
+		y = r.y1;
+		src_w = drm_rect_width(&r);
+		src_h = drm_rect_height(&r);
+
+		stride_div = intel_tile_height(dev_priv, fb->modifier[0],
+					       pixel_size);
+		stride = intel_fb->plane[0].rotated.pitch;
 	} else {
-		stride = fb->pitches[0] / stride_div;
-		x_offset = x;
-		y_offset = y;
-		plane_size = (src_h - 1) << 16 | (src_w - 1);
+		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+						       fb->pixel_format);
+		stride = fb->pitches[0];
 	}
-	plane_offset = y_offset << 16 | x_offset;
 
-	intel_crtc->adjusted_x = x_offset;
-	intel_crtc->adjusted_y = y_offset;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
+	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
+					      stride, rotation);
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	dst_w--;
+	dst_h--;
+
+	intel_crtc->adjusted_x = x;
+	intel_crtc->adjusted_y = y;
 
 	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
-	I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
-	I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
-	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
+	I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
+	I915_WRITE(PLANE_STRIDE(pipe, 0), stride / stride_div);
+	I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w);
 
 	if (scaler_id >= 0) {
 		uint32_t ps_ctrl = 0;
@@ -3237,7 +3403,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 		I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);
 	}
 
-	I915_WRITE(PLANE_SURF(pipe, 0), surf_addr);
+	I915_WRITE(PLANE_SURF(pipe, 0),
+		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
 
 	POSTING_READ(PLANE_SURF(pipe, 0));
 }
@@ -11521,8 +11688,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	if (ret)
 		goto cleanup_pending;
 
-	work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
-						  obj, 0);
+	work->gtt_offset = intel_surf_gtt_offset(fb, 0, primary->state->rotation);
 	work->gtt_offset += intel_crtc->dspaddr_offset;
 
 	if (mmio_flip) {
@@ -14319,7 +14485,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
 				  struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	unsigned int aligned_height;
 	int ret;
 	u32 pitch_limit, stride_alignment;
 
@@ -14443,16 +14608,13 @@ static int intel_framebuffer_init(struct drm_device *dev,
 	if (ret)
 		return ret;
 
-	aligned_height = intel_fb_align_height(dev, mode_cmd->height,
-					       mode_cmd->pixel_format,
-					       mode_cmd->modifier[0]);
-	/* FIXME drm helper for size checks (especially planar formats)? */
-	if (obj->base.size < aligned_height * mode_cmd->pitches[0])
-		return -EINVAL;
-
 	drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
 	intel_fb->obj = obj;
 
+	ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
+	if (ret)
+		return ret;
+
 	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
 	if (ret) {
 		DRM_ERROR("framebuffer init failed %d\n", ret);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 36d049d..395afd3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -118,6 +118,19 @@ enum intel_output_type {
 struct intel_framebuffer {
 	struct drm_framebuffer base;
 	struct drm_i915_gem_object *obj;
+	struct intel_rotation_info info;
+
+	struct {
+		struct {
+			/* pixels */
+			unsigned int x, y;
+		} normal;
+		struct {
+			/* pixels */
+			unsigned int x, y;
+			unsigned int pitch;
+		} rotated;
+	} plane[2];
 };
 
 struct intel_fbdev {
@@ -1028,6 +1041,12 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv);
 void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *info);
+unsigned int intel_fb_xy_to_linear(int x, int y,
+				   const struct drm_framebuffer *fb, int plane);
+void intel_add_fb_offsets(int *x, int *y,
+			  const struct drm_framebuffer *fb, int plane,
+			  unsigned int rotation);
 extern const struct drm_plane_funcs intel_plane_funcs;
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
 int intel_pch_rawclk(struct drm_device *dev);
@@ -1134,10 +1153,10 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
 void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
-unsigned long intel_compute_page_offset(int *x, int *y,
-					const struct drm_framebuffer *fb, int plane,
-					unsigned int pitch,
-					unsigned int rotation);
+unsigned int intel_compute_page_offset(int *x, int *y,
+				       const struct drm_framebuffer *fb, int plane,
+				       unsigned int pitch,
+				       unsigned int rotation);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
 void hsw_enable_pc8(struct drm_i915_private *dev_priv);
@@ -1174,9 +1193,8 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
 
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
-				     struct drm_i915_gem_object *obj,
-				     unsigned int plane);
+unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
+				   unsigned int rotation);
 
 u32 skl_plane_ctl_format(uint32_t pixel_format);
 u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 828c3eb..d9d37b0 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -188,17 +188,15 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	struct drm_device *dev = drm_plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
-	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
 	const int pipe = intel_plane->pipe;
 	const int plane = intel_plane->plane + 1;
 	u32 plane_ctl, stride_div, stride;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(drm_plane->state)->ckey;
-	unsigned long surf_addr;
-	u32 tile_height, plane_offset, plane_size;
+	unsigned int surf_addr;
 	unsigned int rotation;
-	int x_offset, y_offset;
 	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
 	int scaler_id;
 
@@ -215,17 +213,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 				       pixel_size, true,
 				       src_w != crtc_w || src_h != crtc_h);
 
-	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
-					       fb->pixel_format);
-
 	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
 
-	/* Sizes are 0 based */
-	src_w--;
-	src_h--;
-	crtc_w--;
-	crtc_h--;
-
 	if (key->flags) {
 		I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
 		I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
@@ -237,27 +226,43 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
 
-	surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
-
 	if (intel_rotation_90_or_270(rotation)) {
-		/* stride: Surface height in tiles */
-		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
-						pixel_size);
-		stride = DIV_ROUND_UP(fb->height, tile_height);
-		plane_size = (src_w << 16) | src_h;
-		x_offset = stride * tile_height - y - (src_h + 1);
-		y_offset = x;
+		struct drm_rect r = {
+			.x1 = x,
+			.x2 = x + src_w,
+			.y1 = y,
+			.y2 = y + src_h,
+		};
+
+		/* Rotate src coordinates to match rotated GTT view */
+		drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
+
+		x = r.x1;
+		y = r.y1;
+		src_w = drm_rect_width(&r);
+		src_h = drm_rect_height(&r);
+
+		stride_div = intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
+		stride = intel_fb->plane[0].rotated.pitch;
 	} else {
-		stride = fb->pitches[0] / stride_div;
-		plane_size = (src_h << 16) | src_w;
-		x_offset = x;
-		y_offset = y;
+		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+						       fb->pixel_format);
+		stride = fb->pitches[0];
 	}
-	plane_offset = y_offset << 16 | x_offset;
 
-	I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
-	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
-	I915_WRITE(PLANE_SIZE(pipe, plane), plane_size);
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
+	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
+					      stride, rotation);
+
+	/* Sizes are 0 based */
+	src_w--;
+	src_h--;
+	crtc_w--;
+	crtc_h--;
+
+	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
+	I915_WRITE(PLANE_STRIDE(pipe, plane), stride / stride_div);
+	I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
 
 	/* program plane scaler */
 	if (scaler_id >= 0) {
@@ -279,7 +284,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	}
 
 	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
-	I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
+	I915_WRITE(PLANE_SURF(pipe, plane),
+		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
 	POSTING_READ(PLANE_SURF(pipe, plane));
 }
 
@@ -355,8 +361,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	int plane = intel_plane->plane;
 	u32 sprctl;
 	unsigned int rotation = dplane->state->rotation;
-	unsigned long sprsurf_offset, linear_offset;
-	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+	unsigned int sprsurf_offset, linear_offset;
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(dplane->state)->ckey;
 
@@ -420,19 +425,19 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 	crtc_w--;
 	crtc_h--;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
-	linear_offset -= sprsurf_offset;
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SP_ROTATE_180;
 
 		x += src_w;
 		y += src_h;
-		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	if (key->flags) {
 		I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
 		I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
@@ -457,8 +462,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 
 	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
 	I915_WRITE(SPCNTR(pipe, plane), sprctl);
-	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
-		   sprsurf_offset);
+	I915_WRITE(SPSURF(pipe, plane),
+		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
 	POSTING_READ(SPSURF(pipe, plane));
 }
 
@@ -492,7 +497,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	enum pipe pipe = intel_plane->pipe;
 	u32 sprctl, sprscale = 0;
 	unsigned int rotation = plane->state->rotation;
-	unsigned long sprsurf_offset, linear_offset;
+	unsigned int sprsurf_offset, linear_offset;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
 		&to_intel_plane_state(plane->state)->ckey;
@@ -552,10 +557,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (crtc_w != src_w || crtc_h != src_h)
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
-	linear_offset -= sprsurf_offset;
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SPRITE_ROTATE_180;
@@ -564,11 +568,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
 			x += src_w;
 			y += src_h;
-			linear_offset += src_h * fb->pitches[0] +
-				src_w * pixel_size;
 		}
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	if (key->flags) {
 		I915_WRITE(SPRKEYVAL(pipe), key->min_value);
 		I915_WRITE(SPRKEYMAX(pipe), key->max_value);
@@ -597,7 +601,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 		I915_WRITE(SPRSCALE(pipe), sprscale);
 	I915_WRITE(SPRCTL(pipe), sprctl);
 	I915_WRITE(SPRSURF(pipe),
-		   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
+		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -632,7 +636,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	int pipe = intel_plane->pipe;
 	unsigned int rotation = plane->state->rotation;
-	unsigned long dvssurf_offset, linear_offset;
+	unsigned int dvssurf_offset, linear_offset;
 	u32 dvscntr, dvsscale;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key =
@@ -689,19 +693,19 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	if (crtc_w != src_w || crtc_h != src_h)
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
-	linear_offset = y * fb->pitches[0] + x * pixel_size;
+	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
 	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
 						   fb->pitches[0], rotation);
-	linear_offset -= dvssurf_offset;
 
 	if (rotation == BIT(DRM_ROTATE_180)) {
 		dvscntr |= DVS_ROTATE_180;
 
 		x += src_w;
 		y += src_h;
-		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
 	}
 
+	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
 	if (key->flags) {
 		I915_WRITE(DVSKEYVAL(pipe), key->min_value);
 		I915_WRITE(DVSKEYMAX(pipe), key->max_value);
@@ -725,7 +729,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 	I915_WRITE(DVSSCALE(pipe), dvsscale);
 	I915_WRITE(DVSCNTR(pipe), dvscntr);
 	I915_WRITE(DVSSURF(pipe),
-		   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
+		   intel_surf_gtt_offset(fb, 0, rotation) + dvssurf_offset);
 	POSTING_READ(DVSSURF(pipe));
 }
 
-- 
2.4.9

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* Re: [PATCH 01/22] drm: Add drm_format_plane_width() and drm_format_plane_height()
  2015-10-14 16:28 ` [PATCH 01/22] drm: Add drm_format_plane_width() and drm_format_plane_height() ville.syrjala
@ 2015-10-21  9:53   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21  9:53 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx, dri-devel

On Wed, Oct 14, 2015 at 07:28:53PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add a few helpers to get the dimensions of the chroma plane(s).
> 
> Cc: dri-devel@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  include/drm/drm_crtc.h | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 33ddedd..317baf9 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -1497,6 +1497,18 @@ extern int drm_format_num_planes(uint32_t format);
>  extern int drm_format_plane_cpp(uint32_t format, int plane);
>  extern int drm_format_horz_chroma_subsampling(uint32_t format);
>  extern int drm_format_vert_chroma_subsampling(uint32_t format);
> +static inline int drm_format_plane_width(int width, uint32_t format, int plane)
> +{
> +	if (plane == 0)
> +		return width;
> +	return width / drm_format_horz_chroma_subsampling(format);
> +}
> +static inline int drm_format_plane_height(int height, uint32_t format, int plane)
> +{
> +	if (plane == 0)
> +		return height;
> +	return height / drm_format_vert_chroma_subsampling(format);
> +}

A bit of kerneldoc would be neat. Either way Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  extern const char *drm_get_format_name(uint32_t format);
>  extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
>  							      unsigned int supported_rotations);
> -- 
> 2.4.9
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 02/22] drm/i915: Pass modifier instead of tiling_mode to gen4_compute_page_offset()
  2015-10-14 16:28 ` [PATCH 02/22] drm/i915: Pass modifier instead of tiling_mode to gen4_compute_page_offset() ville.syrjala
@ 2015-10-21  9:54   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21  9:54 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:28:54PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> In preparation for handling more than X tiling, pass the fb modifier to
> gen4_compute_page_offset() instead of the obj->tiling_mode.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 8 ++++----
>  drivers/gpu/drm/i915/intel_drv.h     | 4 ++--
>  drivers/gpu/drm/i915/intel_sprite.c  | 6 +++---
>  3 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c28fb6a..6add8d1 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2447,11 +2447,11 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
>   * is assumed to be a power-of-two. */
>  unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
>  					     int *x, int *y,
> -					     unsigned int tiling_mode,
> +					     uint64_t fb_modifier,
>  					     unsigned int cpp,
>  					     unsigned int pitch)
>  {
> -	if (tiling_mode != I915_TILING_NONE) {
> +	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
>  		unsigned int tile_rows, tiles;
>  
>  		tile_rows = *y / 8;
> @@ -2754,7 +2754,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  	if (INTEL_INFO(dev)->gen >= 4) {
>  		intel_crtc->dspaddr_offset =
>  			intel_gen4_compute_page_offset(dev_priv,
> -						       &x, &y, obj->tiling_mode,
> +						       &x, &y, fb->modifier[0],
>  						       pixel_size,
>  						       fb->pitches[0]);
>  		linear_offset -= intel_crtc->dspaddr_offset;
> @@ -2859,7 +2859,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	intel_crtc->dspaddr_offset =
>  		intel_gen4_compute_page_offset(dev_priv,
> -					       &x, &y, obj->tiling_mode,
> +					       &x, &y, fb->modifier[0],
>  					       pixel_size,
>  					       fb->pitches[0]);
>  	linear_offset -= intel_crtc->dspaddr_offset;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 0598932..1152566 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1138,8 +1138,8 @@ void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
>  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
>  unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
>  					     int *x, int *y,
> -					     unsigned int tiling_mode,
> -					     unsigned int bpp,
> +					     uint64_t fb_modifier,
> +					     unsigned int cpp,
>  					     unsigned int pitch);
>  void intel_prepare_reset(struct drm_device *dev);
>  void intel_finish_reset(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index b229c67..90e27c8 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -422,7 +422,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
>  							&x, &y,
> -							obj->tiling_mode,
> +							fb->modifier[0],
>  							pixel_size,
>  							fb->pitches[0]);
>  	linear_offset -= sprsurf_offset;
> @@ -556,7 +556,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	sprsurf_offset =
>  		intel_gen4_compute_page_offset(dev_priv,
> -					       &x, &y, obj->tiling_mode,
> +					       &x, &y, fb->modifier[0],
>  					       pixel_size, fb->pitches[0]);
>  	linear_offset -= sprsurf_offset;
>  
> @@ -694,7 +694,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	dvssurf_offset =
>  		intel_gen4_compute_page_offset(dev_priv,
> -					       &x, &y, obj->tiling_mode,
> +					       &x, &y, fb->modifier[0],
>  					       pixel_size, fb->pitches[0]);
>  	linear_offset -= dvssurf_offset;
>  
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 03/22] drm/i915: Factor out intel_tile_width()
  2015-10-14 16:28 ` [PATCH 03/22] drm/i915: Factor out intel_tile_width() ville.syrjala
@ 2015-10-21 10:15   ` Daniel Vetter
  2015-10-21 12:09     ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 10:15 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:28:55PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Pull the tile width calculations from intel_fb_stride_alignment() into a
> new function intel_tile_width().
> 
> Also take the opportunity to pass aroun dev_priv instead of dev to
> intel_fb_stride_alignment().
> 
> v2: Reorder argumnents to be more consistent with other functions
>     Change intel_fb_stride_alignment() to accept dev_priv instead of dev
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 76 +++++++++++++++++++++++-------------
>  drivers/gpu/drm/i915/intel_drv.h     |  4 +-
>  drivers/gpu/drm/i915/intel_sprite.c  |  2 +-
>  3 files changed, 51 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 6add8d1..c31fe47 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2214,6 +2214,41 @@ static bool need_vtd_wa(struct drm_device *dev)
>  	return false;
>  }
>  
> +static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
> +				     uint64_t fb_modifier, unsigned int cpp)
> +{
> +	switch (fb_modifier) {
> +	case DRM_FORMAT_MOD_NONE:
> +		return cpp;
> +	case I915_FORMAT_MOD_X_TILED:
> +		return IS_GEN2(dev_priv) ? 128 : 512;
> +	case I915_FORMAT_MOD_Y_TILED:
> +		/* No need to check for old gens and Y tiling since this is
> +		 * about the display engine and those will be blocked before
> +		 * we get here.
> +		 */
> +		return 128;

Imo just drop the comment and change this to

		return HAS_128_BYTE_Y_TILING(dev) 128 : 512;

Just to avoid wtf moments. It's less code than the comment too.

Another one: Enforcing pot alignment for gen2/3 is fairly hapzardous - we
do it accidentally by requiring that for X-tiled the underlying obj is
also X-tiled and that strides match. Comment for this would be good here.

> +	case I915_FORMAT_MOD_Yf_TILED:
> +		switch (cpp) {
> +		case 1:
> +			return 64;
> +		case 2:
> +		case 4:
> +			return 128;

With 4 cpp we have 4x4 pixels for the 64b cacheline. So 8x8 for the 256b
block with 1:1 aspect ratio, hence 64x64 pixel tile for the full page.

> +		case 8:

With 8 cpp we have 2x4 pixels for the 64b cacheline. So 8x4 for the 256b
block with 2:1 aspect ratio, hence 64x32 pixel tile for the full page.

> +		case 16:
> +			return 256;

With 16 cpp we have 1x4 pixels for the 64b cacheline. So 4x4 for the 256b
block with 1:1 aspect ratio, hence 32x32 pixel tile for the full page.

Otherwise looks good to me, Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
once we close the above.

Cheers, Daniel

> +		default:
> +			MISSING_CASE(cpp);
> +			return cpp;
> +		}
> +		break;
> +	default:
> +		MISSING_CASE(fb_modifier);
> +		return cpp;
> +	}
> +}
> +
>  unsigned int
>  intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
>  		  uint64_t fb_format_modifier, unsigned int plane)
> @@ -2895,37 +2930,20 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  	POSTING_READ(reg);
>  }
>  
> -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
> -			      uint32_t pixel_format)
> +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> +			      uint64_t fb_modifier, uint32_t pixel_format)
>  {
> -	u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
> -
>  	/*
>  	 * The stride is either expressed as a multiple of 64 bytes
>  	 * chunks for linear buffers or in number of tiles for tiled
>  	 * buffers.
>  	 */
> -	switch (fb_modifier) {
> -	case DRM_FORMAT_MOD_NONE:
> -		return 64;
> -	case I915_FORMAT_MOD_X_TILED:
> -		if (INTEL_INFO(dev)->gen == 2)
> -			return 128;
> -		return 512;
> -	case I915_FORMAT_MOD_Y_TILED:
> -		/* No need to check for old gens and Y tiling since this is
> -		 * about the display engine and those will be blocked before
> -		 * we get here.
> -		 */
> -		return 128;
> -	case I915_FORMAT_MOD_Yf_TILED:
> -		if (bits_per_pixel == 8)
> -			return 64;
> -		else
> -			return 128;
> -	default:
> -		MISSING_CASE(fb_modifier);
> +	if (fb_modifier == DRM_FORMAT_MOD_NONE) {
>  		return 64;
> +	} else {
> +		unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
> +
> +		return intel_tile_width(dev_priv, fb_modifier, cpp);
>  	}
>  }
>  
> @@ -3106,7 +3124,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  	plane_ctl |= skl_plane_ctl_rotation(rotation);
>  
>  	obj = intel_fb_obj(fb);
> -	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> +	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
>  					       fb->pixel_format);
>  	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
>  
> @@ -9066,7 +9084,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
>  	fb->width = ((val >> 0) & 0x1fff) + 1;
>  
>  	val = I915_READ(PLANE_STRIDE(pipe, 0));
> -	stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
> +	stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
>  						fb->pixel_format);
>  	fb->pitches[0] = (val & 0x3ff) * stride_mult;
>  
> @@ -11137,7 +11155,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
>  	 * linear buffers or in number of tiles for tiled buffers.
>  	 */
>  	stride = fb->pitches[0] /
> -		 intel_fb_stride_alignment(dev, fb->modifier[0],
> +		 intel_fb_stride_alignment(dev_priv, fb->modifier[0],
>  					   fb->pixel_format);
>  
>  	/*
> @@ -14214,6 +14232,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  				  struct drm_mode_fb_cmd2 *mode_cmd,
>  				  struct drm_i915_gem_object *obj)
>  {
> +	struct drm_i915_private *dev_priv = to_i915(dev);
>  	unsigned int aligned_height;
>  	int ret;
>  	u32 pitch_limit, stride_alignment;
> @@ -14255,7 +14274,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  		return -EINVAL;
>  	}
>  
> -	stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
> +	stride_alignment = intel_fb_stride_alignment(dev_priv,
> +						     mode_cmd->modifier[0],
>  						     mode_cmd->pixel_format);
>  	if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
>  		DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1152566..98a8d31 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1017,8 +1017,8 @@ unsigned int intel_fb_align_height(struct drm_device *dev,
>  				   uint64_t fb_format_modifier);
>  void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire,
>  			enum fb_op_origin origin);
> -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
> -			      uint32_t pixel_format);
> +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> +			      uint64_t fb_modifier, uint32_t pixel_format);
>  
>  /* intel_audio.c */
>  void intel_init_audio(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 90e27c8..3d96871 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -215,7 +215,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  				       pixel_size, true,
>  				       src_w != crtc_w || src_h != crtc_h);
>  
> -	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> +	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
>  					       fb->pixel_format);
>  
>  	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 04/22] drm/i915: Redo intel_tile_height() as intel_tile_size() / intel_tile_width()
  2015-10-14 16:28 ` [PATCH 04/22] drm/i915: Redo intel_tile_height() as intel_tile_size() / intel_tile_width() ville.syrjala
@ 2015-10-21 10:21   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 10:21 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:28:56PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> I find more usual to think about tile widths than heights, so changing
> the intel_tile_height() to calculate the tile height as
> tile_size/tile_width is easier than the opposite to the poor brain.
> 
> v2: Reorder arguments for consistency
>     Constify dev_priv arguments
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 88 ++++++++++++------------------------
>  drivers/gpu/drm/i915/intel_drv.h     |  5 +-
>  drivers/gpu/drm/i915/intel_sprite.c  |  4 +-
>  3 files changed, 34 insertions(+), 63 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c31fe47..d028326 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2214,6 +2214,11 @@ static bool need_vtd_wa(struct drm_device *dev)
>  	return false;
>  }
>  
> +static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
> +{
> +	return IS_GEN2(dev_priv) ? 2048 : 4096;
> +}
> +
>  static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
>  				     uint64_t fb_modifier, unsigned int cpp)
>  {
> @@ -2249,67 +2254,34 @@ static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
>  	}
>  }
>  
> -unsigned int
> -intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
> -		  uint64_t fb_format_modifier, unsigned int plane)
> +unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
> +			       uint64_t fb_modifier, unsigned int cpp)
>  {
> -	unsigned int tile_height;
> -	uint32_t pixel_bytes;
> -
> -	switch (fb_format_modifier) {
> -	case DRM_FORMAT_MOD_NONE:
> -		tile_height = 1;
> -		break;
> -	case I915_FORMAT_MOD_X_TILED:
> -		tile_height = IS_GEN2(dev) ? 16 : 8;
> -		break;
> -	case I915_FORMAT_MOD_Y_TILED:
> -		tile_height = 32;
> -		break;
> -	case I915_FORMAT_MOD_Yf_TILED:
> -		pixel_bytes = drm_format_plane_cpp(pixel_format, plane);
> -		switch (pixel_bytes) {
> -		default:
> -		case 1:
> -			tile_height = 64;
> -			break;
> -		case 2:
> -		case 4:
> -			tile_height = 32;
> -			break;
> -		case 8:
> -			tile_height = 16;

Minus math fail, this here seems to match what I've come up with. Given
that's fixed this is Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

One thing to consider is to shovel all the tile helpers into
i915_gem_tiling.c and add some kerneldoc. Just to avoid intel_display.c
becoming even more a dumpster pile of random things.

One more bikeshed comment below.

> -			break;
> -		case 16:
> -			WARN_ONCE(1,
> -				  "128-bit pixels are not supported for display!");
> -			tile_height = 16;
> -			break;
> -		}
> -		break;
> -	default:
> -		MISSING_CASE(fb_format_modifier);
> -		tile_height = 1;
> -		break;
> -	}
> -
> -	return tile_height;
> +	if (fb_modifier == DRM_FORMAT_MOD_NONE)
> +		return 1;
> +	else
> +		return intel_tile_size(dev_priv) /
> +			intel_tile_width(dev_priv, fb_modifier, cpp);
>  }
>  
>  unsigned int
>  intel_fb_align_height(struct drm_device *dev, unsigned int height,
> -		      uint32_t pixel_format, uint64_t fb_format_modifier)
> +		      uint32_t pixel_format, uint64_t fb_modifier)
>  {
> -	return ALIGN(height, intel_tile_height(dev, pixel_format,
> -					       fb_format_modifier, 0));
> +	unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
> +	unsigned int tile_height = intel_tile_height(to_i915(dev), fb_modifier, cpp);
> +
> +	return ALIGN(height, tile_height);
>  }
>  
>  static int
>  intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>  			const struct drm_plane_state *plane_state)
>  {
> +	struct drm_i915_private *dev_priv = to_i915(fb->dev);
>  	struct intel_rotation_info *info = &view->rotation_info;
>  	unsigned int tile_height, tile_pitch;
> +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
>  
>  	*view = i915_ggtt_view_normal;
>  
> @@ -2327,22 +2299,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>  	info->uv_offset = fb->offsets[1];
>  	info->fb_modifier = fb->modifier[0];
>  
> -	tile_height = intel_tile_height(fb->dev, fb->pixel_format,
> -					fb->modifier[0], 0);
> +	tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
>  	tile_pitch = PAGE_SIZE / tile_height;
>  	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
>  	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
>  	info->size = info->width_pages * info->height_pages * PAGE_SIZE;
>  
>  	if (info->pixel_format == DRM_FORMAT_NV12) {
> -		tile_height = intel_tile_height(fb->dev, fb->pixel_format,
> -						fb->modifier[0], 1);
> +		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
> +		tile_height = intel_tile_height(dev_priv, fb->modifier[1], cpp);
>  		tile_pitch = PAGE_SIZE / tile_height;
> -		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
> -		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
> -						     tile_height);
> -		info->size_uv = info->width_pages_uv * info->height_pages_uv *
> -				PAGE_SIZE;
> +		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_pitch);
> +		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);

I guess a follow-up patch will emplouy your shiny new helpers here?

Cheers, Daniel

> +		info->size_uv = info->width_pages_uv * info->height_pages_uv * PAGE_SIZE;
>  	}
>  
>  	return 0;
> @@ -3102,6 +3071,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
>  	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
>  	int scaler_id = -1;
> +	int pixel_size;
>  
>  	plane_state = to_intel_plane_state(plane->state);
>  
> @@ -3112,6 +3082,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  		return;
>  	}
>  
> +	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> +
>  	plane_ctl = PLANE_CTL_ENABLE |
>  		    PLANE_CTL_PIPE_GAMMA_ENABLE |
>  		    PLANE_CTL_PIPE_CSC_ENABLE;
> @@ -3144,8 +3116,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  
>  	if (intel_rotation_90_or_270(rotation)) {
>  		/* stride = Surface height in tiles */
> -		tile_height = intel_tile_height(dev, fb->pixel_format,
> -						fb->modifier[0], 0);
> +		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> +						pixel_size);
>  		stride = DIV_ROUND_UP(fb->height, tile_height);
>  		x_offset = stride * tile_height - y - src_h;
>  		y_offset = x;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 98a8d31..429f744 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1095,9 +1095,8 @@ int intel_plane_atomic_set_property(struct drm_plane *plane,
>  int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
>  				    struct drm_plane_state *plane_state);
>  
> -unsigned int
> -intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
> -		  uint64_t fb_format_modifier, unsigned int plane);
> +unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
> +			       uint64_t fb_modifier, unsigned int cpp);
>  
>  static inline bool
>  intel_rotation_90_or_270(unsigned int rotation)
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 3d96871..4a1a5f4 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -241,8 +241,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  
>  	if (intel_rotation_90_or_270(rotation)) {
>  		/* stride: Surface height in tiles */
> -		tile_height = intel_tile_height(dev, fb->pixel_format,
> -						fb->modifier[0], 0);
> +		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> +						pixel_size);
>  		stride = DIV_ROUND_UP(fb->height, tile_height);
>  		plane_size = (src_w << 16) | src_h;
>  		x_offset = stride * tile_height - y - (src_h + 1);
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 05/22] drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size
  2015-10-14 16:28 ` [PATCH 05/22] drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size ville.syrjala
@ 2015-10-21 10:22   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 10:22 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:28:57PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Use the actual tile size as to compute stuff in
> intel_fill_fb_ggtt_view() instead of assuming it's PAGE_SIZE. I suppose
> it doesn't matter since we don't use the results on gen2 platforms
> where the tile size is 2k.

Well maybe 64k Ys will eventually happen as a super-maxfifo mode for
performance in games ;-)

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> 
> v2: Update due to CbCr plane
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 24 ++++++++++++++----------
>  1 file changed, 14 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index d028326..c8b2907 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2280,8 +2280,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(fb->dev);
>  	struct intel_rotation_info *info = &view->rotation_info;
> -	unsigned int tile_height, tile_pitch;
> -	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> +	unsigned int tile_size, tile_width, tile_height, cpp;
>  
>  	*view = i915_ggtt_view_normal;
>  
> @@ -2299,19 +2298,24 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>  	info->uv_offset = fb->offsets[1];
>  	info->fb_modifier = fb->modifier[0];
>  
> -	tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
> -	tile_pitch = PAGE_SIZE / tile_height;
> -	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
> +	tile_size = intel_tile_size(dev_priv);
> +
> +	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> +	tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
> +	tile_height = tile_size / tile_width;
> +
> +	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
>  	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
> -	info->size = info->width_pages * info->height_pages * PAGE_SIZE;
> +	info->size = info->width_pages * info->height_pages * tile_size;
>  
>  	if (info->pixel_format == DRM_FORMAT_NV12) {
>  		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
> -		tile_height = intel_tile_height(dev_priv, fb->modifier[1], cpp);
> -		tile_pitch = PAGE_SIZE / tile_height;
> -		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_pitch);
> +		tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
> +		tile_height = tile_size / tile_width;
> +
> +		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
>  		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
> -		info->size_uv = info->width_pages_uv * info->height_pages_uv * PAGE_SIZE;
> +		info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
>  	}
>  
>  	return 0;
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 06/22] drm/i915: Use intel_tile_{size, width, height}() in intel_gen4_compute_page_offset()
  2015-10-14 16:28 ` [PATCH 06/22] drm/i915: Use intel_tile_{size, width, height}() in intel_gen4_compute_page_offset() ville.syrjala
@ 2015-10-21 10:24   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 10:24 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:28:58PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Make intel_gen4_compute_page_offset() ready for other tiling formats
> besied X-tile by getting the tile dimensions through
> intel_tile_{size,width,height}().
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c8b2907..509fcac 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2460,15 +2460,20 @@ unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
>  					     unsigned int pitch)
>  {

For consistency I'd rename it to compute_tile_offset then. Since it might
or might not be a page any more. Can be done in a follow-up. And that
tile_offset helper would be pretty in i915_gem_tiling.c too I'd say.

Anyway Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
> +		unsigned int tile_size, tile_width, tile_height;
>  		unsigned int tile_rows, tiles;
>  
> -		tile_rows = *y / 8;
> -		*y %= 8;
> +		tile_size = intel_tile_size(dev_priv);
> +		tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
> +		tile_height = tile_size / tile_width;
> +
> +		tile_rows = *y / tile_height;
> +		*y %= tile_height;
>  
> -		tiles = *x / (512/cpp);
> -		*x %= 512/cpp;
> +		tiles = *x / (tile_width/cpp);
> +		*x %= tile_width/cpp;
>  
> -		return tile_rows * pitch * 8 + tiles * 4096;
> +		return tile_rows * pitch * tile_height + tiles * tile_size;
>  	} else {
>  		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
>  		unsigned int offset;
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 07/22] drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/
  2015-10-14 16:28 ` [PATCH 07/22] drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/ ville.syrjala
@ 2015-10-21 10:45   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 10:45 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:28:59PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Since intel_gen4_compute_page_offset() can now handle tiling formats
> all the way down to gen2, rename it to intel_compute_page_offset().
> Not that we actually use it on gen2/3 since there's no DSPSURF etc.
> registers which would take a page aligned address.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Per my comment on the previous patch I'd call this
intel_compute_tile_offset. With that

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 24 +++++++++++-------------
>  drivers/gpu/drm/i915/intel_drv.h     | 10 +++++-----
>  drivers/gpu/drm/i915/intel_sprite.c  | 22 +++++++++-------------
>  3 files changed, 25 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 509fcac..75be66b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2453,11 +2453,11 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
>  
>  /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
>   * is assumed to be a power-of-two. */
> -unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
> -					     int *x, int *y,
> -					     uint64_t fb_modifier,
> -					     unsigned int cpp,
> -					     unsigned int pitch)
> +unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> +					int *x, int *y,
> +					uint64_t fb_modifier,
> +					unsigned int cpp,
> +					unsigned int pitch)
>  {
>  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
>  		unsigned int tile_size, tile_width, tile_height;
> @@ -2766,10 +2766,9 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  
>  	if (INTEL_INFO(dev)->gen >= 4) {
>  		intel_crtc->dspaddr_offset =
> -			intel_gen4_compute_page_offset(dev_priv,
> -						       &x, &y, fb->modifier[0],
> -						       pixel_size,
> -						       fb->pitches[0]);
> +			intel_compute_page_offset(dev_priv, &x, &y,
> +						  fb->modifier[0], pixel_size,
> +						  fb->pitches[0]);
>  		linear_offset -= intel_crtc->dspaddr_offset;
>  	} else {
>  		intel_crtc->dspaddr_offset = linear_offset;
> @@ -2871,10 +2870,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	intel_crtc->dspaddr_offset =
> -		intel_gen4_compute_page_offset(dev_priv,
> -					       &x, &y, fb->modifier[0],
> -					       pixel_size,
> -					       fb->pitches[0]);
> +		intel_compute_page_offset(dev_priv, &x, &y,
> +					  fb->modifier[0], pixel_size,
> +					  fb->pitches[0]);
>  	linear_offset -= intel_crtc->dspaddr_offset;
>  	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
>  		dspcntr |= DISPPLANE_ROTATE_180;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 429f744..a12ac95 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1135,11 +1135,11 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
>  void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
>  #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
>  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
> -unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
> -					     int *x, int *y,
> -					     uint64_t fb_modifier,
> -					     unsigned int cpp,
> -					     unsigned int pitch);
> +unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> +					int *x, int *y,
> +					uint64_t fb_modifier,
> +					unsigned int cpp,
> +					unsigned int pitch);
>  void intel_prepare_reset(struct drm_device *dev);
>  void intel_finish_reset(struct drm_device *dev);
>  void hsw_enable_pc8(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 4a1a5f4..6614adb 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -420,11 +420,9 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	crtc_h--;
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> -	sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
> -							&x, &y,
> -							fb->modifier[0],
> -							pixel_size,
> -							fb->pitches[0]);
> +	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> +						   fb->modifier[0], pixel_size,
> +						   fb->pitches[0]);
>  	linear_offset -= sprsurf_offset;
>  
>  	if (dplane->state->rotation == BIT(DRM_ROTATE_180)) {
> @@ -554,10 +552,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> -	sprsurf_offset =
> -		intel_gen4_compute_page_offset(dev_priv,
> -					       &x, &y, fb->modifier[0],
> -					       pixel_size, fb->pitches[0]);
> +	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> +						   fb->modifier[0], pixel_size,
> +						   fb->pitches[0]);
>  	linear_offset -= sprsurf_offset;
>  
>  	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
> @@ -692,10 +689,9 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> -	dvssurf_offset =
> -		intel_gen4_compute_page_offset(dev_priv,
> -					       &x, &y, fb->modifier[0],
> -					       pixel_size, fb->pitches[0]);
> +	dvssurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> +						   fb->modifier[0], pixel_size,
> +						   fb->pitches[0]);
>  	linear_offset -= dvssurf_offset;
>  
>  	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
  2015-10-14 16:29 ` [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
@ 2015-10-21 10:53   ` Daniel Vetter
  2015-10-21 11:36     ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 10:53 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:00PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The page aligned surface address calculation needs to know which way
> things are rotated. The contract now says that the caller must pass the
> rotate x/y coordinates, as well as the tile_height aligned stride in
> the tile_height direction. This will make it fairly simple to deal with
> 90/270 degree rotation on SKL+ where we have to deal with the rotated
> view into the GTT.
> 
> v2: Pass rotation instead of bool even thoughwe only care about 0/180 vs. 90/270
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 62 ++++++++++++++++++++++++++++++------
>  drivers/gpu/drm/i915/intel_drv.h     |  3 +-
>  drivers/gpu/drm/i915/intel_sprite.c  | 15 +++++----
>  3 files changed, 64 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 75be66b..bd55d06 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2451,13 +2451,50 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
>  	i915_gem_object_unpin_from_display_plane(obj, &view);
>  }
>  
> -/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
> - * is assumed to be a power-of-two. */
> +/*
> + * Return the tile dimensions in pixel units matching
> + * the specified rotation angle.
> + */
> +static void intel_rotate_tile_dims(unsigned int *tile_width,
> +				   unsigned int *tile_height,
> +				   unsigned int *pitch,
> +				   unsigned int cpp,
> +				   unsigned int rotation)

A rotation enum would be nice, so that we can employ sparse to check it.
That'd work since sparse treats enums as bitfields, but we'd need to
add names for the BIT(DRM_ROTATION_*) variants. Just an aside.

> +{
> +	if (intel_rotation_90_or_270(rotation)) {
> +		WARN_ON(*pitch % *tile_height);
> +
> +		/* pixel units please */
> +		*tile_width /= cpp;

Ok, something dawns on me now about tile_width ... it's in bytes, I
somehow thought it's pixels. And this function doing a behind-the-scenes
conversions from bytes to pixels is a bit tricky.

Should we have separate tile_pitch and tile_width to unconfuse this?
Generally foo_width in the modeset code is mostly pixels ...

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> on this one (and I
retract my earlier review on tile_width), but I'd like something clearer
here in the end ...

Cheers, Daniel

> +
> +		/*
> +		 * Coordinate space is rotated, orient
> +		 * our tile dimensions the same way
> +		 */
> +		swap(*tile_width, *tile_height);
> +	} else {
> +		WARN_ON(*pitch % *tile_width);
> +
> +		/* pixel units please */
> +		*tile_width /= cpp;
> +		*pitch /= cpp;
> +	}
> +}
> +
> +/*
> + * Computes the linear offset to the base tile and adjusts
> + * x, y. bytes per pixel is assumed to be a power-of-two.
> + *
> + * In the 90/270 rotated case, x and y are assumed
> + * to be already rotated to match the rotated GTT view, and
> + * pitch is the tile_height aligned framebuffer height.
> + */
>  unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
>  					int *x, int *y,
>  					uint64_t fb_modifier,
>  					unsigned int cpp,
> -					unsigned int pitch)
> +					unsigned int pitch,
> +					unsigned int rotation)
>  {
>  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
>  		unsigned int tile_size, tile_width, tile_height;
> @@ -2467,13 +2504,16 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
>  		tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
>  		tile_height = tile_size / tile_width;
>  
> +		intel_rotate_tile_dims(&tile_width, &tile_height,
> +				       &pitch, cpp, rotation);
> +
>  		tile_rows = *y / tile_height;
>  		*y %= tile_height;
>  
> -		tiles = *x / (tile_width/cpp);
> -		*x %= tile_width/cpp;
> +		tiles = *x / tile_width;
> +		*x %= tile_width;
>  
> -		return tile_rows * pitch * tile_height + tiles * tile_size;
> +		return (tile_rows * (pitch / tile_width) + tiles) * tile_size;
>  	} else {
>  		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
>  		unsigned int offset;
> @@ -2685,6 +2725,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  	bool visible = to_intel_plane_state(primary->state)->visible;
>  	struct drm_i915_gem_object *obj;
>  	int plane = intel_crtc->plane;
> +	unsigned int rotation;
>  	unsigned long linear_offset;
>  	u32 dspcntr;
>  	u32 reg = DSPCNTR(plane);
> @@ -2704,6 +2745,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  	if (WARN_ON(obj == NULL))
>  		return;
>  
> +	rotation = crtc->primary->state->rotation;
>  	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  
>  	dspcntr = DISPPLANE_GAMMA_ENABLE;
> @@ -2768,7 +2810,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  		intel_crtc->dspaddr_offset =
>  			intel_compute_page_offset(dev_priv, &x, &y,
>  						  fb->modifier[0], pixel_size,
> -						  fb->pitches[0]);
> +						  fb->pitches[0], rotation);
>  		linear_offset -= intel_crtc->dspaddr_offset;
>  	} else {
>  		intel_crtc->dspaddr_offset = linear_offset;
> @@ -2814,6 +2856,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  	bool visible = to_intel_plane_state(primary->state)->visible;
>  	struct drm_i915_gem_object *obj;
>  	int plane = intel_crtc->plane;
> +	unsigned int rotation;
>  	unsigned long linear_offset;
>  	u32 dspcntr;
>  	u32 reg = DSPCNTR(plane);
> @@ -2830,6 +2873,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  	if (WARN_ON(obj == NULL))
>  		return;
>  
> +	rotation = crtc->primary->state->rotation;
>  	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  
>  	dspcntr = DISPPLANE_GAMMA_ENABLE;
> @@ -2872,9 +2916,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  	intel_crtc->dspaddr_offset =
>  		intel_compute_page_offset(dev_priv, &x, &y,
>  					  fb->modifier[0], pixel_size,
> -					  fb->pitches[0]);
> +					  fb->pitches[0], rotation);
>  	linear_offset -= intel_crtc->dspaddr_offset;
> -	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
> +	if (rotation == BIT(DRM_ROTATE_180)) {
>  		dspcntr |= DISPPLANE_ROTATE_180;
>  
>  		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index a12ac95..ed47ca3 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1139,7 +1139,8 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
>  					int *x, int *y,
>  					uint64_t fb_modifier,
>  					unsigned int cpp,
> -					unsigned int pitch);
> +					unsigned int pitch,
> +					unsigned int rotation);
>  void intel_prepare_reset(struct drm_device *dev);
>  void intel_finish_reset(struct drm_device *dev);
>  void hsw_enable_pc8(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 6614adb..8eaebce 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -354,6 +354,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	int pipe = intel_plane->pipe;
>  	int plane = intel_plane->plane;
>  	u32 sprctl;
> +	unsigned int rotation = dplane->state->rotation;
>  	unsigned long sprsurf_offset, linear_offset;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  	const struct drm_intel_sprite_colorkey *key =
> @@ -422,10 +423,10 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
>  						   fb->modifier[0], pixel_size,
> -						   fb->pitches[0]);
> +						   fb->pitches[0], rotation);
>  	linear_offset -= sprsurf_offset;
>  
> -	if (dplane->state->rotation == BIT(DRM_ROTATE_180)) {
> +	if (rotation == BIT(DRM_ROTATE_180)) {
>  		sprctl |= SP_ROTATE_180;
>  
>  		x += src_w;
> @@ -491,6 +492,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>  	enum pipe pipe = intel_plane->pipe;
>  	u32 sprctl, sprscale = 0;
> +	unsigned int rotation = plane->state->rotation;
>  	unsigned long sprsurf_offset, linear_offset;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  	const struct drm_intel_sprite_colorkey *key =
> @@ -554,10 +556,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
>  						   fb->modifier[0], pixel_size,
> -						   fb->pitches[0]);
> +						   fb->pitches[0], rotation);
>  	linear_offset -= sprsurf_offset;
>  
> -	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
> +	if (rotation == BIT(DRM_ROTATE_180)) {
>  		sprctl |= SPRITE_ROTATE_180;
>  
>  		/* HSW and BDW does this automagically in hardware */
> @@ -631,6 +633,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	struct intel_plane *intel_plane = to_intel_plane(plane);
>  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>  	int pipe = intel_plane->pipe;
> +	unsigned int rotation = plane->state->rotation;
>  	unsigned long dvssurf_offset, linear_offset;
>  	u32 dvscntr, dvsscale;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> @@ -691,10 +694,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	dvssurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
>  						   fb->modifier[0], pixel_size,
> -						   fb->pitches[0]);
> +						   fb->pitches[0], rotation);
>  	linear_offset -= dvssurf_offset;
>  
> -	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
> +	if (rotation == BIT(DRM_ROTATE_180)) {
>  		dvscntr |= DVS_ROTATE_180;
>  
>  		x += src_w;
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 09/22] drm/i915: Refactor intel_surf_alignment()
  2015-10-14 16:29 ` [PATCH 09/22] drm/i915: Refactor intel_surf_alignment() ville.syrjala
@ 2015-10-21 10:54   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 10:54 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:01PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Pull the code to determine the surface alignment for both linear and
> tiled surfaces into a separate function intel_surf_alignment(). This
> will be used not only for the vma alignment but actually aligning
> the plane SURF once SKL+ starts using intel_compute_page_offset()
> (since SKL+ needs >4K alignment for tiled surfaces too).
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 45 +++++++++++++++++-------------------
>  1 file changed, 21 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index bd55d06..5f3abce 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2321,7 +2321,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>  	return 0;
>  }
>  
> -static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
> +static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
>  {
>  	if (INTEL_INFO(dev_priv)->gen >= 9)
>  		return 256 * 1024;
> @@ -2334,6 +2334,25 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
>  		return 0;
>  }
>  
> +static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv,
> +					 uint64_t fb_modifier)
> +{
> +	switch (fb_modifier) {
> +	case DRM_FORMAT_MOD_NONE:
> +		return intel_linear_alignment(dev_priv);
> +	case I915_FORMAT_MOD_X_TILED:
> +		if (INTEL_INFO(dev_priv)->gen >= 9)
> +			return 256 * 1024;
> +		return 0;
> +	case I915_FORMAT_MOD_Y_TILED:
> +	case I915_FORMAT_MOD_Yf_TILED:
> +		return 1 * 1024 * 1024;
> +	default:
> +		MISSING_CASE(fb_modifier);
> +		return 0;
> +	}
> +}
> +
>  int
>  intel_pin_and_fence_fb_obj(struct drm_plane *plane,
>  			   struct drm_framebuffer *fb,
> @@ -2350,29 +2369,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
>  
>  	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
>  
> -	switch (fb->modifier[0]) {
> -	case DRM_FORMAT_MOD_NONE:
> -		alignment = intel_linear_alignment(dev_priv);
> -		break;
> -	case I915_FORMAT_MOD_X_TILED:
> -		if (INTEL_INFO(dev)->gen >= 9)
> -			alignment = 256 * 1024;
> -		else {
> -			/* pin() will align the object as required by fence */
> -			alignment = 0;
> -		}
> -		break;
> -	case I915_FORMAT_MOD_Y_TILED:
> -	case I915_FORMAT_MOD_Yf_TILED:
> -		if (WARN_ONCE(INTEL_INFO(dev)->gen < 9,
> -			  "Y tiling bo slipped through, driver bug!\n"))
> -			return -EINVAL;
> -		alignment = 1 * 1024 * 1024;
> -		break;
> -	default:
> -		MISSING_CASE(fb->modifier[0]);
> -		return -EINVAL;
> -	}
> +	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
>  
>  	ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
>  	if (ret)
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces
  2015-10-14 16:29 ` [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
@ 2015-10-21 11:22   ` Daniel Vetter
  2015-10-21 11:32     ` Daniel Vetter
  2015-10-21 11:39     ` Ville Syrjälä
  0 siblings, 2 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:22 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:02PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> SKL+ needs >4K alignment for tiled surfaces, so make
> intel_compute_page_offset() handle it.
> 
> The way we do it is first we compute the closest tile boundary
> as before, and then figure out how many tiles we need to go
> to reach the desired alignment. The difference in the offset
> is then added into the x/y offsets.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++++++++++----
>  1 file changed, 46 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 5f3abce..85e1473 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2479,6 +2479,39 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
>  }
>  
>  /*
> + * Adjust the page 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.
> + * intel_rotate_tile_dims() gives exactly that.
> + */
> +static void intel_adjust_page_offset(int *x, int *y,
> +				     unsigned int tile_width,
> +				     unsigned int tile_height,
> +				     unsigned int tile_size,
> +				     unsigned int pitch,
> +				     unsigned int old_offset,
> +				     unsigned int new_offset)
> +{
> +	unsigned int tiles;
> +
> +	WARN_ON(old_offset & (tile_size - 1));
> +	WARN_ON(new_offset & (tile_size - 1));
> +	WARN_ON(new_offset > old_offset);
> +
> +	tiles = (old_offset - new_offset) / tile_size;
> +	if (tiles == 0)
> +		return;
> +
> +	/* pitch in tiles */
> +	pitch /= tile_width;

Isn't tile_width here now in pixels and no longer in bytes? And we need
bytes here I think, i.e. tile_pitch.

> +
> +	*y += tiles / pitch * tile_height;
> +	*x += tiles % pitch * tile_width;

But here we need tile_width in pixels. I'm confused.

> +}
> +
> +/*
>   * Computes the linear offset to the base tile and adjusts
>   * x, y. bytes per pixel is assumed to be a power-of-two.
>   *
> @@ -2493,6 +2526,12 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
>  					unsigned int pitch,
>  					unsigned int rotation)
>  {
> +	unsigned int offset, alignment;
> +
> +	alignment = intel_surf_alignment(dev_priv, fb_modifier);
> +	if (alignment)
> +		alignment--;
> +
>  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
>  		unsigned int tile_size, tile_width, tile_height;
>  		unsigned int tile_rows, tiles;
> @@ -2510,16 +2549,18 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
>  		tiles = *x / tile_width;
>  		*x %= tile_width;
>  
> -		return (tile_rows * (pitch / tile_width) + tiles) * tile_size;
> -	} else {
> -		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
> -		unsigned int offset;
> +		offset = (tile_rows * (pitch / tile_width) + tiles) * tile_size;
>  
> +		intel_adjust_page_offset(x, y, tile_width, tile_height,
> +					 tile_size, pitch,
> +					 offset, offset & ~alignment);

offset_aligned = ALIGN(offset, alignment); instead of open-coding it.
-Daniel

> +	} else {
>  		offset = *y * pitch + *x * cpp;
>  		*y = (offset & alignment) / pitch;
>  		*x = ((offset & alignment) - *y * pitch) / cpp;
> -		return offset & ~alignment;
>  	}
> +
> +	return offset & ~alignment;
>  }
>  
>  static int i9xx_format_to_fourcc(int format)
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-14 16:29 ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
  2015-10-15  9:08   ` Chris Wilson
  2015-10-15 11:10   ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() Tvrtko Ursulin
@ 2015-10-21 11:28   ` Daniel Vetter
  2015-10-21 12:17     ` Tvrtko Ursulin
  2 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:28 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> rotation (to find the right GTT view for it), so no need to pass all
> kinds of plane stuff.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Feels indeed a bit like a bikeshed and just churn without resolving the
"pass vma in plane_state around" idea for real. But meh, it's imo not
worse than the existing code, and looks correct. Less churn would make me
a happier reviewer thought (there's a pile of whitespace in here too).

Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++--------------------
>  drivers/gpu/drm/i915/intel_drv.h     |  5 ++---
>  drivers/gpu/drm/i915/intel_fbdev.c   |  2 +-
>  3 files changed, 20 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 85e1473..80e9f2e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2275,8 +2275,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
>  }
>  
>  static int
> -intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> -			const struct drm_plane_state *plane_state)
> +intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> +			const struct drm_framebuffer *fb,
> +			unsigned int rotation)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(fb->dev);
>  	struct intel_rotation_info *info = &view->rotation_info;
> @@ -2284,10 +2285,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
>  
>  	*view = i915_ggtt_view_normal;
>  
> -	if (!plane_state)
> -		return 0;
> -
> -	if (!intel_rotation_90_or_270(plane_state->rotation))
> +	if (!intel_rotation_90_or_270(rotation))
>  		return 0;
>  
>  	*view = i915_ggtt_view_rotated;
> @@ -2354,9 +2352,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv
>  }
>  
>  int
> -intel_pin_and_fence_fb_obj(struct drm_plane *plane,
> -			   struct drm_framebuffer *fb,
> -			   const struct drm_plane_state *plane_state,
> +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
> +			   unsigned int rotation,
>  			   struct intel_engine_cs *pipelined,
>  			   struct drm_i915_gem_request **pipelined_request)
>  {
> @@ -2371,7 +2368,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
>  
>  	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
>  
> -	ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
> +	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
>  	if (ret)
>  		return ret;
>  
> @@ -2432,8 +2429,7 @@ err_interruptible:
>  	return ret;
>  }
>  
> -static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
> -			       const struct drm_plane_state *plane_state)
> +static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
>  {
>  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>  	struct i915_ggtt_view view;
> @@ -2441,7 +2437,7 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
>  
>  	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
>  
> -	ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
> +	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
>  	WARN_ONCE(ret, "Couldn't get view from plane state!");
>  
>  	i915_gem_object_unpin_fence(obj);
> @@ -10780,7 +10776,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
>  	struct drm_plane *primary = crtc->base.primary;
>  
>  	mutex_lock(&dev->struct_mutex);
> -	intel_unpin_fb_obj(work->old_fb, primary->state);
> +	intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
>  	drm_gem_object_unreference(&work->pending_flip_obj->base);
>  
>  	if (work->flip_queued_req)
> @@ -11521,8 +11517,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  	 * synchronisation, so all we want here is to pin the framebuffer
>  	 * into the display plane and skip any waits.
>  	 */
> -	ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
> -					 crtc->primary->state,
> +	ret = intel_pin_and_fence_fb_obj(fb, primary->state->rotation,
>  					 mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring, &request);
>  	if (ret)
>  		goto cleanup_pending;
> @@ -11573,7 +11568,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  	return 0;
>  
>  cleanup_unpin:
> -	intel_unpin_fb_obj(fb, crtc->primary->state);
> +	intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
>  cleanup_pending:
>  	if (request)
>  		i915_gem_request_cancel(request);
> @@ -13457,7 +13452,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
>  		if (ret)
>  			DRM_DEBUG_KMS("failed to attach phys object\n");
>  	} else {
> -		ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL, NULL);
> +		ret = intel_pin_and_fence_fb_obj(fb, new_state->rotation,
> +						 NULL, NULL);
>  	}
>  
>  	if (ret == 0)
> @@ -13488,7 +13484,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
>  	if (plane->type != DRM_PLANE_TYPE_CURSOR ||
>  	    !INTEL_INFO(dev)->cursor_needs_physical) {
>  		mutex_lock(&dev->struct_mutex);
> -		intel_unpin_fb_obj(old_state->fb, old_state);
> +		intel_unpin_fb_obj(old_state->fb, old_state->rotation);
>  		mutex_unlock(&dev->struct_mutex);
>  	}
>  }
> @@ -15474,9 +15470,8 @@ void intel_modeset_gem_init(struct drm_device *dev)
>  			continue;
>  
>  		mutex_lock(&dev->struct_mutex);
> -		ret = intel_pin_and_fence_fb_obj(c->primary,
> -						 c->primary->fb,
> -						 c->primary->state,
> +		ret = intel_pin_and_fence_fb_obj(c->primary->fb,
> +						 c->primary->state->rotation,
>  						 NULL, NULL);
>  		mutex_unlock(&dev->struct_mutex);
>  		if (ret) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index ed47ca3..b0d92e0 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1067,9 +1067,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
>  void intel_release_load_detect_pipe(struct drm_connector *connector,
>  				    struct intel_load_detect_pipe *old,
>  				    struct drm_modeset_acquire_ctx *ctx);
> -int intel_pin_and_fence_fb_obj(struct drm_plane *plane,
> -			       struct drm_framebuffer *fb,
> -			       const struct drm_plane_state *plane_state,
> +int intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
> +			       unsigned int rotation,
>  			       struct intel_engine_cs *pipelined,
>  			       struct drm_i915_gem_request **pipelined_request);
>  struct drm_framebuffer *
> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> index 4fd5fdf..6bef820 100644
> --- a/drivers/gpu/drm/i915/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> @@ -161,7 +161,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
>  	}
>  
>  	/* Flush everything out, we'll be doing GTT only from now on */
> -	ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL, NULL, NULL);
> +	ret = intel_pin_and_fence_fb_obj(fb, BIT(DRM_ROTATE_0), NULL, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to pin obj: %d\n", ret);
>  		goto out_fb;
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly
  2015-10-15 12:01     ` Daniel Vetter
@ 2015-10-21 11:28       ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:28 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 02:01:38PM +0200, Daniel Vetter wrote:
> On Thu, Oct 15, 2015 at 12:15:21PM +0100, Tvrtko Ursulin wrote:
> > 
> > Hi,
> > 
> > On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> > >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > >Just for clarity set the type for i915_ggtt_view_normal explicitly.
> > >
> > >While at it fix the indentation fail for i915_ggtt_view_rotated.
> > >
> > >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >---
> > >  drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++--
> > >  1 file changed, 4 insertions(+), 2 deletions(-)
> > >
> > >diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > >index 620d57e..71acc71 100644
> > >--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> > >+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > >@@ -95,9 +95,11 @@
> > >  static int
> > >  i915_get_ggtt_vma_pages(struct i915_vma *vma);
> > >
> > >-const struct i915_ggtt_view i915_ggtt_view_normal;
> > >+const struct i915_ggtt_view i915_ggtt_view_normal = {
> > >+	.type = I915_GGTT_VIEW_NORMAL,
> > >+};
> > 
> > AFAIR while this was developed Daniel was very keen on the normal view type
> > being implicitly zero. Can't remember at this very moment if some of the
> > current code actually depends on it though.
> 
> We kzalloc vmas, which means any view in there is normal by default. Still
> very much keen on that ;-)

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 13/22] drm/i915: Move the partial and rotated view data into the same union
  2015-10-14 16:29 ` [PATCH 13/22] drm/i915: Move the partial and rotated view data into the same union ville.syrjala
@ 2015-10-21 11:30   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:30 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:05PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Each gtt view only has a single type, and so don't need to contain data
> for both rotated and partial views. So we can move the data into the
> same union to avoid wasting space.
> 
> Also rename 'rotation_info' to 'rotated' to match the view type exactly,
> this should avoid confusion which union members is valid for each view
> type. Also make the union anonymous to avoid the .params. stuff all
> over.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem.c      | 10 +++++-----
>  drivers/gpu/drm/i915/i915_gem_gtt.c  | 12 ++++++------
>  drivers/gpu/drm/i915/i915_gem_gtt.h  | 11 ++++-------
>  drivers/gpu/drm/i915/intel_display.c |  4 ++--
>  4 files changed, 17 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index e57061a..b93ed18 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1772,12 +1772,12 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>  
>  		memset(&view, 0, sizeof(view));
>  		view.type = I915_GGTT_VIEW_PARTIAL;
> -		view.params.partial.offset = rounddown(page_offset, chunk_size);
> -		view.params.partial.size =
> +		view.partial.offset = rounddown(page_offset, chunk_size);
> +		view.partial.size =
>  			min_t(unsigned int,
>  			      chunk_size,
>  			      (vma->vm_end - vma->vm_start)/PAGE_SIZE -
> -			      view.params.partial.offset);
> +			      view.partial.offset);
>  	}
>  
>  	/* Now pin it into the GTT if needed */
> @@ -1805,10 +1805,10 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>  		 * having accessed it before (at this partials' range).
>  		 */
>  		unsigned long base = vma->vm_start +
> -				     (view.params.partial.offset << PAGE_SHIFT);
> +				     (view.partial.offset << PAGE_SHIFT);
>  		unsigned int i;
>  
> -		for (i = 0; i < view.params.partial.size; i++) {
> +		for (i = 0; i < view.partial.size; i++) {
>  			ret = vm_insert_pfn(vma, base + i * PAGE_SIZE, pfn + i);
>  			if (ret)
>  				break;
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index 71acc71..e0baff2 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -3282,7 +3282,7 @@ static struct sg_table *
>  intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
>  			  struct drm_i915_gem_object *obj)
>  {
> -	struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
> +	struct intel_rotation_info *rot_info = &ggtt_view->rotated;
>  	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
>  	unsigned int size_pages_uv;
>  	struct sg_page_iter sg_iter;
> @@ -3380,16 +3380,16 @@ intel_partial_pages(const struct i915_ggtt_view *view,
>  	if (!st)
>  		goto err_st_alloc;
>  
> -	ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
> +	ret = sg_alloc_table(st, view->partial.size, GFP_KERNEL);
>  	if (ret)
>  		goto err_sg_alloc;
>  
>  	sg = st->sgl;
>  	st->nents = 0;
>  	for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
> -		view->params.partial.offset)
> +		view->partial.offset)
>  	{
> -		if (st->nents >= view->params.partial.size)
> +		if (st->nents >= view->partial.size)
>  			break;
>  
>  		sg_set_page(sg, NULL, PAGE_SIZE, 0);
> @@ -3514,9 +3514,9 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
>  	if (view->type == I915_GGTT_VIEW_NORMAL) {
>  		return obj->base.size;
>  	} else if (view->type == I915_GGTT_VIEW_ROTATED) {
> -		return view->rotation_info.size;
> +		return view->rotated.size;
>  	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
> -		return view->params.partial.size << PAGE_SHIFT;
> +		return view->partial.size << PAGE_SHIFT;
>  	} else {
>  		WARN_ONCE(1, "GGTT view %u not implemented!\n", view->type);
>  		return obj->base.size;
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index a216397..caa182f 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -151,17 +151,14 @@ struct intel_rotation_info {
>  struct i915_ggtt_view {
>  	enum i915_ggtt_view_type type;
>  
> +	struct sg_table *pages;
> +
>  	union {
> +		struct intel_rotation_info rotated;
>  		struct {
>  			u64 offset;
>  			unsigned int size;
>  		} partial;
> -	} params;

If you keep the name for this union (to future-proof the next patch):

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>

aka I trust your compiler to get this right ;-)

Cheers, Daniel

> -
> -	struct sg_table *pages;
> -
> -	union {
> -		struct intel_rotation_info rotation_info;
>  	};
>  };
>  
> @@ -557,7 +554,7 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
>  	if (a->type != b->type)
>  		return false;
>  	if (a->type == I915_GGTT_VIEW_PARTIAL)
> -		return !memcmp(&a->params, &b->params, sizeof(a->params));
> +		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
>  	return true;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 80e9f2e..ce346cfe 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2280,7 +2280,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
>  			unsigned int rotation)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(fb->dev);
> -	struct intel_rotation_info *info = &view->rotation_info;
> +	struct intel_rotation_info *info = &view->rotated;
>  	unsigned int tile_size, tile_width, tile_height, cpp;
>  
>  	*view = i915_ggtt_view_normal;
> @@ -3020,7 +3020,7 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
>  	offset = (unsigned char *)vma->node.start;
>  
>  	if (plane == 1) {
> -		offset += vma->ggtt_view.rotation_info.uv_start_page *
> +		offset += vma->ggtt_view.rotated.uv_start_page *
>  			  PAGE_SIZE;
>  	}
>  
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces
  2015-10-21 11:22   ` Daniel Vetter
@ 2015-10-21 11:32     ` Daniel Vetter
  2015-10-21 11:39     ` Ville Syrjälä
  1 sibling, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:32 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 01:22:43PM +0200, Daniel Vetter wrote:
> On Wed, Oct 14, 2015 at 07:29:02PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > SKL+ needs >4K alignment for tiled surfaces, so make
> > intel_compute_page_offset() handle it.
> > 
> > The way we do it is first we compute the closest tile boundary
> > as before, and then figure out how many tiles we need to go
> > to reach the desired alignment. The difference in the offset
> > is then added into the x/y offsets.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++++++++++----
> >  1 file changed, 46 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 5f3abce..85e1473 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2479,6 +2479,39 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
> >  }
> >  
> >  /*
> > + * Adjust the page 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.
> > + * intel_rotate_tile_dims() gives exactly that.
> > + */
> > +static void intel_adjust_page_offset(int *x, int *y,
> > +				     unsigned int tile_width,
> > +				     unsigned int tile_height,
> > +				     unsigned int tile_size,
> > +				     unsigned int pitch,
> > +				     unsigned int old_offset,
> > +				     unsigned int new_offset)
> > +{
> > +	unsigned int tiles;
> > +
> > +	WARN_ON(old_offset & (tile_size - 1));
> > +	WARN_ON(new_offset & (tile_size - 1));
> > +	WARN_ON(new_offset > old_offset);
> > +
> > +	tiles = (old_offset - new_offset) / tile_size;
> > +	if (tiles == 0)
> > +		return;
> > +
> > +	/* pitch in tiles */
> > +	pitch /= tile_width;
> 
> Isn't tile_width here now in pixels and no longer in bytes? And we need
> bytes here I think, i.e. tile_pitch.
> 
> > +
> > +	*y += tiles / pitch * tile_height;
> > +	*x += tiles % pitch * tile_width;
> 
> But here we need tile_width in pixels. I'm confused.

Looking harder I realized that you also adjust the pitch in the rotation
patch. Imo that's pulling a few too many tricks, we really need to clear
up tile_width (imo pixels) vs. tile_pitch (imo bytes) vs. pitch (always in
pixels). But that can be done later on.

> > +}
> > +
> > +/*
> >   * Computes the linear offset to the base tile and adjusts
> >   * x, y. bytes per pixel is assumed to be a power-of-two.
> >   *
> > @@ -2493,6 +2526,12 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> >  					unsigned int pitch,
> >  					unsigned int rotation)
> >  {
> > +	unsigned int offset, alignment;
> > +
> > +	alignment = intel_surf_alignment(dev_priv, fb_modifier);
> > +	if (alignment)
> > +		alignment--;
> > +
> >  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
> >  		unsigned int tile_size, tile_width, tile_height;
> >  		unsigned int tile_rows, tiles;
> > @@ -2510,16 +2549,18 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> >  		tiles = *x / tile_width;
> >  		*x %= tile_width;
> >  
> > -		return (tile_rows * (pitch / tile_width) + tiles) * tile_size;
> > -	} else {
> > -		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
> > -		unsigned int offset;
> > +		offset = (tile_rows * (pitch / tile_width) + tiles) * tile_size;
> >  
> > +		intel_adjust_page_offset(x, y, tile_width, tile_height,
> > +					 tile_size, pitch,
> > +					 offset, offset & ~alignment);
> 
> offset_aligned = ALIGN(offset, alignment); instead of open-coding it.

So with myself unconfused, if you apply the ALIGN:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal
  2015-10-14 16:29 ` [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal ville.syrjala
  2015-10-15 11:18   ` Tvrtko Ursulin
@ 2015-10-21 11:36   ` Daniel Vetter
  1 sibling, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:36 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:06PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> In case we have multiple different rotated views into the same object,
> each one may need its own vma due to being of different sizes. So don't
> treat all rotated views as equal.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index caa182f..68de734 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -553,6 +553,8 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
>  
>  	if (a->type != b->type)
>  		return false;
> +	if (a->type == I915_GGTT_VIEW_ROTATED)
> +		return !memcmp(&a->rotated, &b->rotated, sizeof(a->rotated));

We should take my "[PATCH 3/3] drm/i915: Fix i915_ggtt_view_equal to
handle rotation correctly" instead since being more strict here means
intel_plane_obj_offset won't find the prepared view any more.

Another reasons to just track the vma in the plane_state.
-Daniel
>  	if (a->type == I915_GGTT_VIEW_PARTIAL)
>  		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
>  	return true;
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
  2015-10-21 10:53   ` Daniel Vetter
@ 2015-10-21 11:36     ` Ville Syrjälä
  2015-10-21 12:11       ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 11:36 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 12:53:34PM +0200, Daniel Vetter wrote:
> On Wed, Oct 14, 2015 at 07:29:00PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > The page aligned surface address calculation needs to know which way
> > things are rotated. The contract now says that the caller must pass the
> > rotate x/y coordinates, as well as the tile_height aligned stride in
> > the tile_height direction. This will make it fairly simple to deal with
> > 90/270 degree rotation on SKL+ where we have to deal with the rotated
> > view into the GTT.
> > 
> > v2: Pass rotation instead of bool even thoughwe only care about 0/180 vs. 90/270
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 62 ++++++++++++++++++++++++++++++------
> >  drivers/gpu/drm/i915/intel_drv.h     |  3 +-
> >  drivers/gpu/drm/i915/intel_sprite.c  | 15 +++++----
> >  3 files changed, 64 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 75be66b..bd55d06 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2451,13 +2451,50 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
> >  	i915_gem_object_unpin_from_display_plane(obj, &view);
> >  }
> >  
> > -/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
> > - * is assumed to be a power-of-two. */
> > +/*
> > + * Return the tile dimensions in pixel units matching
> > + * the specified rotation angle.
> > + */
> > +static void intel_rotate_tile_dims(unsigned int *tile_width,
> > +				   unsigned int *tile_height,
> > +				   unsigned int *pitch,
> > +				   unsigned int cpp,
> > +				   unsigned int rotation)
> 
> A rotation enum would be nice, so that we can employ sparse to check it.
> That'd work since sparse treats enums as bitfields, but we'd need to
> add names for the BIT(DRM_ROTATION_*) variants. Just an aside.

I was thinking of including the '1<<x' in the define already since the
current thing just invites bugs all over. I guess making it an enum at
the same time should be easy.

> 
> > +{
> > +	if (intel_rotation_90_or_270(rotation)) {
> > +		WARN_ON(*pitch % *tile_height);
> > +
> > +		/* pixel units please */
> > +		*tile_width /= cpp;
> 
> Ok, something dawns on me now about tile_width ... it's in bytes, I
> somehow thought it's pixels. And this function doing a behind-the-scenes
> conversions from bytes to pixels is a bit tricky.
> 
> Should we have separate tile_pitch and tile_width to unconfuse this?
> Generally foo_width in the modeset code is mostly pixels ...

Yeah, things are a bit unclear with bytes vs. pixels sometimes. I
usually think of tile width as bytes because then you don't have to
consider the pixel format (well, except for Yf/Ys tiling), but here
we want it in pixels instead.

I'm not sure tile_pitch is a good name becuse then it might get
confused with the pitch for the fb or fence. But I don't really have
a better name in mind either.

> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> on this one (and I
> retract my earlier review on tile_width), but I'd like something clearer
> here in the end ...
> 
> Cheers, Daniel
> 
> > +
> > +		/*
> > +		 * Coordinate space is rotated, orient
> > +		 * our tile dimensions the same way
> > +		 */
> > +		swap(*tile_width, *tile_height);
> > +	} else {
> > +		WARN_ON(*pitch % *tile_width);
> > +
> > +		/* pixel units please */
> > +		*tile_width /= cpp;
> > +		*pitch /= cpp;
> > +	}
> > +}
> > +
> > +/*
> > + * Computes the linear offset to the base tile and adjusts
> > + * x, y. bytes per pixel is assumed to be a power-of-two.
> > + *
> > + * In the 90/270 rotated case, x and y are assumed
> > + * to be already rotated to match the rotated GTT view, and
> > + * pitch is the tile_height aligned framebuffer height.
> > + */
> >  unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> >  					int *x, int *y,
> >  					uint64_t fb_modifier,
> >  					unsigned int cpp,
> > -					unsigned int pitch)
> > +					unsigned int pitch,
> > +					unsigned int rotation)
> >  {
> >  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
> >  		unsigned int tile_size, tile_width, tile_height;
> > @@ -2467,13 +2504,16 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> >  		tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
> >  		tile_height = tile_size / tile_width;
> >  
> > +		intel_rotate_tile_dims(&tile_width, &tile_height,
> > +				       &pitch, cpp, rotation);
> > +
> >  		tile_rows = *y / tile_height;
> >  		*y %= tile_height;
> >  
> > -		tiles = *x / (tile_width/cpp);
> > -		*x %= tile_width/cpp;
> > +		tiles = *x / tile_width;
> > +		*x %= tile_width;
> >  
> > -		return tile_rows * pitch * tile_height + tiles * tile_size;
> > +		return (tile_rows * (pitch / tile_width) + tiles) * tile_size;
> >  	} else {
> >  		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
> >  		unsigned int offset;
> > @@ -2685,6 +2725,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
> >  	bool visible = to_intel_plane_state(primary->state)->visible;
> >  	struct drm_i915_gem_object *obj;
> >  	int plane = intel_crtc->plane;
> > +	unsigned int rotation;
> >  	unsigned long linear_offset;
> >  	u32 dspcntr;
> >  	u32 reg = DSPCNTR(plane);
> > @@ -2704,6 +2745,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
> >  	if (WARN_ON(obj == NULL))
> >  		return;
> >  
> > +	rotation = crtc->primary->state->rotation;
> >  	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  
> >  	dspcntr = DISPPLANE_GAMMA_ENABLE;
> > @@ -2768,7 +2810,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
> >  		intel_crtc->dspaddr_offset =
> >  			intel_compute_page_offset(dev_priv, &x, &y,
> >  						  fb->modifier[0], pixel_size,
> > -						  fb->pitches[0]);
> > +						  fb->pitches[0], rotation);
> >  		linear_offset -= intel_crtc->dspaddr_offset;
> >  	} else {
> >  		intel_crtc->dspaddr_offset = linear_offset;
> > @@ -2814,6 +2856,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> >  	bool visible = to_intel_plane_state(primary->state)->visible;
> >  	struct drm_i915_gem_object *obj;
> >  	int plane = intel_crtc->plane;
> > +	unsigned int rotation;
> >  	unsigned long linear_offset;
> >  	u32 dspcntr;
> >  	u32 reg = DSPCNTR(plane);
> > @@ -2830,6 +2873,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> >  	if (WARN_ON(obj == NULL))
> >  		return;
> >  
> > +	rotation = crtc->primary->state->rotation;
> >  	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  
> >  	dspcntr = DISPPLANE_GAMMA_ENABLE;
> > @@ -2872,9 +2916,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> >  	intel_crtc->dspaddr_offset =
> >  		intel_compute_page_offset(dev_priv, &x, &y,
> >  					  fb->modifier[0], pixel_size,
> > -					  fb->pitches[0]);
> > +					  fb->pitches[0], rotation);
> >  	linear_offset -= intel_crtc->dspaddr_offset;
> > -	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
> > +	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		dspcntr |= DISPPLANE_ROTATE_180;
> >  
> >  		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index a12ac95..ed47ca3 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1139,7 +1139,8 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> >  					int *x, int *y,
> >  					uint64_t fb_modifier,
> >  					unsigned int cpp,
> > -					unsigned int pitch);
> > +					unsigned int pitch,
> > +					unsigned int rotation);
> >  void intel_prepare_reset(struct drm_device *dev);
> >  void intel_finish_reset(struct drm_device *dev);
> >  void hsw_enable_pc8(struct drm_i915_private *dev_priv);
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> > index 6614adb..8eaebce 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -354,6 +354,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
> >  	int pipe = intel_plane->pipe;
> >  	int plane = intel_plane->plane;
> >  	u32 sprctl;
> > +	unsigned int rotation = dplane->state->rotation;
> >  	unsigned long sprsurf_offset, linear_offset;
> >  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  	const struct drm_intel_sprite_colorkey *key =
> > @@ -422,10 +423,10 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
> >  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> >  	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> >  						   fb->modifier[0], pixel_size,
> > -						   fb->pitches[0]);
> > +						   fb->pitches[0], rotation);
> >  	linear_offset -= sprsurf_offset;
> >  
> > -	if (dplane->state->rotation == BIT(DRM_ROTATE_180)) {
> > +	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		sprctl |= SP_ROTATE_180;
> >  
> >  		x += src_w;
> > @@ -491,6 +492,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >  	enum pipe pipe = intel_plane->pipe;
> >  	u32 sprctl, sprscale = 0;
> > +	unsigned int rotation = plane->state->rotation;
> >  	unsigned long sprsurf_offset, linear_offset;
> >  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  	const struct drm_intel_sprite_colorkey *key =
> > @@ -554,10 +556,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> >  	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> >  						   fb->modifier[0], pixel_size,
> > -						   fb->pitches[0]);
> > +						   fb->pitches[0], rotation);
> >  	linear_offset -= sprsurf_offset;
> >  
> > -	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
> > +	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		sprctl |= SPRITE_ROTATE_180;
> >  
> >  		/* HSW and BDW does this automagically in hardware */
> > @@ -631,6 +633,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	struct intel_plane *intel_plane = to_intel_plane(plane);
> >  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >  	int pipe = intel_plane->pipe;
> > +	unsigned int rotation = plane->state->rotation;
> >  	unsigned long dvssurf_offset, linear_offset;
> >  	u32 dvscntr, dvsscale;
> >  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> > @@ -691,10 +694,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> >  	dvssurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> >  						   fb->modifier[0], pixel_size,
> > -						   fb->pitches[0]);
> > +						   fb->pitches[0], rotation);
> >  	linear_offset -= dvssurf_offset;
> >  
> > -	if (plane->state->rotation == BIT(DRM_ROTATE_180)) {
> > +	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		dvscntr |= DVS_ROTATE_180;
> >  
> >  		x += src_w;
> > -- 
> > 2.4.9
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 15/22] drm/i915: Pass the dma_addr_t array as const to rotate_pages()
  2015-10-14 16:29 ` [PATCH 15/22] drm/i915: Pass the dma_addr_t array as const to rotate_pages() ville.syrjala
@ 2015-10-21 11:36   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:36 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:07PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> rotate_pages() doesn't modify the passed in dma addresses, so make
> them const.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index e0baff2..365a8c6 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -3247,7 +3247,7 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
>  }
>  
>  static struct scatterlist *
> -rotate_pages(dma_addr_t *in, unsigned int offset,
> +rotate_pages(const dma_addr_t *in, unsigned int offset,
>  	     unsigned int width, unsigned int height,
>  	     struct sg_table *st, struct scatterlist *sg)
>  {
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces
  2015-10-21 11:22   ` Daniel Vetter
  2015-10-21 11:32     ` Daniel Vetter
@ 2015-10-21 11:39     ` Ville Syrjälä
  1 sibling, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 11:39 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 01:22:43PM +0200, Daniel Vetter wrote:
> On Wed, Oct 14, 2015 at 07:29:02PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > SKL+ needs >4K alignment for tiled surfaces, so make
> > intel_compute_page_offset() handle it.
> > 
> > The way we do it is first we compute the closest tile boundary
> > as before, and then figure out how many tiles we need to go
> > to reach the desired alignment. The difference in the offset
> > is then added into the x/y offsets.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++++++++++----
> >  1 file changed, 46 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 5f3abce..85e1473 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2479,6 +2479,39 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
> >  }
> >  
> >  /*
> > + * Adjust the page 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.
> > + * intel_rotate_tile_dims() gives exactly that.
> > + */
> > +static void intel_adjust_page_offset(int *x, int *y,
> > +				     unsigned int tile_width,
> > +				     unsigned int tile_height,
> > +				     unsigned int tile_size,
> > +				     unsigned int pitch,
> > +				     unsigned int old_offset,
> > +				     unsigned int new_offset)
> > +{
> > +	unsigned int tiles;
> > +
> > +	WARN_ON(old_offset & (tile_size - 1));
> > +	WARN_ON(new_offset & (tile_size - 1));
> > +	WARN_ON(new_offset > old_offset);
> > +
> > +	tiles = (old_offset - new_offset) / tile_size;
> > +	if (tiles == 0)
> > +		return;
> > +
> > +	/* pitch in tiles */
> > +	pitch /= tile_width;
> 
> Isn't tile_width here now in pixels and no longer in bytes? And we need
> bytes here I think, i.e. tile_pitch.

Everything is in pixels here, apart from the offsets.

> 
> > +
> > +	*y += tiles / pitch * tile_height;
> > +	*x += tiles % pitch * tile_width;
> 
> But here we need tile_width in pixels. I'm confused.
> 
> > +}
> > +
> > +/*
> >   * Computes the linear offset to the base tile and adjusts
> >   * x, y. bytes per pixel is assumed to be a power-of-two.
> >   *
> > @@ -2493,6 +2526,12 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> >  					unsigned int pitch,
> >  					unsigned int rotation)
> >  {
> > +	unsigned int offset, alignment;
> > +
> > +	alignment = intel_surf_alignment(dev_priv, fb_modifier);
> > +	if (alignment)
> > +		alignment--;
> > +
> >  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
> >  		unsigned int tile_size, tile_width, tile_height;
> >  		unsigned int tile_rows, tiles;
> > @@ -2510,16 +2549,18 @@ unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> >  		tiles = *x / tile_width;
> >  		*x %= tile_width;
> >  
> > -		return (tile_rows * (pitch / tile_width) + tiles) * tile_size;
> > -	} else {
> > -		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
> > -		unsigned int offset;
> > +		offset = (tile_rows * (pitch / tile_width) + tiles) * tile_size;
> >  
> > +		intel_adjust_page_offset(x, y, tile_width, tile_height,
> > +					 tile_size, pitch,
> > +					 offset, offset & ~alignment);
> 
> offset_aligned = ALIGN(offset, alignment); instead of open-coding it.

ALIGN() does the wrong thing.

> -Daniel
> 
> > +	} else {
> >  		offset = *y * pitch + *x * cpp;
> >  		*y = (offset & alignment) / pitch;
> >  		*x = ((offset & alignment) - *y * pitch) / cpp;
> > -		return offset & ~alignment;
> >  	}
> > +
> > +	return offset & ~alignment;
> >  }
> >  
> >  static int i9xx_format_to_fourcc(int format)
> > -- 
> > 2.4.9
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned
  2015-10-14 16:29 ` [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
  2015-10-14 16:43   ` Daniel Vetter
@ 2015-10-21 11:41   ` Daniel Vetter
  1 sibling, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:41 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:10PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We convert the fb->offsets[] into x/y offsets, so they must be
> (macro)pixel aligned.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Patches 16-18: Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 36 +++++++++++++++++++++++++++++++++---
>  1 file changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ce346cfe..70e6e27 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14284,6 +14284,36 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
>  	}
>  }
>  
> +static int intel_fb_check_offsets(const struct drm_mode_fb_cmd2 *mode_cmd)
> +{
> +	uint32_t format = mode_cmd->pixel_format;
> +	int i;
> +
> +	for (i = 0; i < drm_format_num_planes(format); i++) {
> +		unsigned int cpp;
> +
> +		switch (format) {
> +		case DRM_FORMAT_YUYV:
> +		case DRM_FORMAT_UYVY:
> +		case DRM_FORMAT_YVYU:
> +		case DRM_FORMAT_VYUY:
> +			cpp = 4;
> +			break;
> +		default:
> +			cpp = drm_format_plane_cpp(format, i);
> +			break;
> +		}
> +
> +		if (mode_cmd->offsets[i] % cpp) {
> +			DRM_DEBUG("fb plane %d offset 0x%08x not (macro)pixel aligned\n",
> +				  i, mode_cmd->offsets[i]);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static int intel_framebuffer_init(struct drm_device *dev,
>  				  struct intel_framebuffer *intel_fb,
>  				  struct drm_mode_fb_cmd2 *mode_cmd,
> @@ -14410,9 +14440,9 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  		return -EINVAL;
>  	}
>  
> -	/* FIXME need to adjust LINOFF/TILEOFF accordingly. */
> -	if (mode_cmd->offsets[0] != 0)
> -		return -EINVAL;
> +	ret = intel_fb_check_offsets(mode_cmd);
> +	if (ret)
> +		return ret;
>  
>  	aligned_height = intel_fb_align_height(dev, mode_cmd->height,
>  					       mode_cmd->pixel_format,
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 19/22] drm/i915: Don't leak framebuffer_references if drm_framebuffer_init() fails
  2015-10-14 16:29 ` [PATCH 19/22] drm/i915: Don't leak framebuffer_references if drm_framebuffer_init() fails ville.syrjala
@ 2015-10-21 11:42   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:42 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:11PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Don't increment obj->framebuffer_references until we know we actually
> managed to create the framebuffer.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 70e6e27..0cfedf9 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14453,7 +14453,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  
>  	drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
>  	intel_fb->obj = obj;
> -	intel_fb->obj->framebuffer_references++;
>  
>  	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
>  	if (ret) {
> @@ -14461,6 +14460,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  		return ret;
>  	}
>  
> +	intel_fb->obj->framebuffer_references++;
> +
>  	return 0;
>  }
>  
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 20/22] drm/i915: Pass drm_frambuffer to intel_compute_page_offset()
  2015-10-14 16:29 ` [PATCH 20/22] drm/i915: Pass drm_frambuffer to intel_compute_page_offset() ville.syrjala
@ 2015-10-21 11:43   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 11:43 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:12PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> intel_compute_page_offsets() gets passed a bunch of the framebuffer
> metadate sepearately. Just pass the framebuffer itself to make life
> simpler for the caller, and make it less likely they would make a
> mistake in the order of the arguments (as most as just unsigned ints and
> such).
> 
> We still pass the pitch explicitly since for 90/270 degree rotation
> the caller has to pass in the right thing.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

So very much, that long list of ints was scary!

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 15 +++++++--------
>  drivers/gpu/drm/i915/intel_drv.h     |  6 ++----
>  drivers/gpu/drm/i915/intel_sprite.c  |  9 +++------
>  3 files changed, 12 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0cfedf9..028dc4a 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2515,13 +2515,14 @@ static void intel_adjust_page_offset(int *x, int *y,
>   * to be already rotated to match the rotated GTT view, and
>   * pitch is the tile_height aligned framebuffer height.
>   */
> -unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> -					int *x, int *y,
> -					uint64_t fb_modifier,
> -					unsigned int cpp,
> +unsigned long intel_compute_page_offset(int *x, int *y,
> +					const struct drm_framebuffer *fb, int plane,
>  					unsigned int pitch,
>  					unsigned int rotation)
>  {
> +	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> +	uint64_t fb_modifier = fb->modifier[plane];
> +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
>  	unsigned int offset, alignment;
>  
>  	alignment = intel_surf_alignment(dev_priv, fb_modifier);
> @@ -2842,8 +2843,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  
>  	if (INTEL_INFO(dev)->gen >= 4) {
>  		intel_crtc->dspaddr_offset =
> -			intel_compute_page_offset(dev_priv, &x, &y,
> -						  fb->modifier[0], pixel_size,
> +			intel_compute_page_offset(&x, &y, fb, 0,
>  						  fb->pitches[0], rotation);
>  		linear_offset -= intel_crtc->dspaddr_offset;
>  	} else {
> @@ -2948,8 +2948,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
>  	intel_crtc->dspaddr_offset =
> -		intel_compute_page_offset(dev_priv, &x, &y,
> -					  fb->modifier[0], pixel_size,
> +		intel_compute_page_offset(&x, &y, fb, 0,
>  					  fb->pitches[0], rotation);
>  	linear_offset -= intel_crtc->dspaddr_offset;
>  	if (rotation == BIT(DRM_ROTATE_180)) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index b0d92e0..36d049d 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1134,10 +1134,8 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
>  void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
>  #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
>  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
> -unsigned long intel_compute_page_offset(struct drm_i915_private *dev_priv,
> -					int *x, int *y,
> -					uint64_t fb_modifier,
> -					unsigned int cpp,
> +unsigned long intel_compute_page_offset(int *x, int *y,
> +					const struct drm_framebuffer *fb, int plane,
>  					unsigned int pitch,
>  					unsigned int rotation);
>  void intel_prepare_reset(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 8eaebce..828c3eb 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -421,8 +421,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	crtc_h--;
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> -	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> -						   fb->modifier[0], pixel_size,
> +	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
>  						   fb->pitches[0], rotation);
>  	linear_offset -= sprsurf_offset;
>  
> @@ -554,8 +553,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> -	sprsurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> -						   fb->modifier[0], pixel_size,
> +	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
>  						   fb->pitches[0], rotation);
>  	linear_offset -= sprsurf_offset;
>  
> @@ -692,8 +690,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
>  
>  	linear_offset = y * fb->pitches[0] + x * pixel_size;
> -	dvssurf_offset = intel_compute_page_offset(dev_priv, &x, &y,
> -						   fb->modifier[0], pixel_size,
> +	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
>  						   fb->pitches[0], rotation);
>  	linear_offset -= dvssurf_offset;
>  
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 21/22] drm/i915: Rewrite fb rotation GTT handling
  2015-10-15 17:59   ` [PATCH v2 " ville.syrjala
@ 2015-10-21 12:01     ` Daniel Vetter
  2015-10-21 14:19       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 12:01 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 08:59:45PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Redo the fb rotation handling in order to:
> - eliminate the NV12 special casing
> - handle fb->offsets[] properly
> - make the rotation handling reasier for the plane code

I think this is too big and should be split a bit. There's also a pile of
renames mixed int on top.

> To achieve these goals we reduce intel_rotation_info to only contain
> (for each plane) the rotated view width,height,stride in tile units,
> and the page offset into the object where the plane starts. Each plane
> is handled exactly the same way, no special casing for NV12 or other
> formats.

That sounds like a good prep patch to split out.

> We then store the computed rotation_info under
> intel_framebuffer so that we don't have to recompute it again.

And another one, plus then following up with the fallout.

This patch also fixes the intel_plane_obj_offset issue for earlier in the
series. Looks good otherwise from reading through it.

> To handle fb->offsets[] we treat them as a linear offsets and convert
> them to x/y offsets from the start of the relevant GTT mapping (either
> normal or rotated). We store the x/y offsets under intel_framebuffer,
> and for some extra convenience we also store the rotated pitch (ie.
> tile aligned plane height). So for each plane we have the normal
> x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
> pitch is available already in fb->pitches[].
> 
> While we're gathering up all that extra information, we can also easily
> compute the storage requirements for the framebuffer, so that we can
> check that the object is big enough to hold it.
> 
> When it comes time to deal with the plane source coordinates, we first
> rotate the clipped src coordinates to match the relevant GTT view
> orientation, then add to them the fb x/y offsets. Next we compute
> the aligned surface page offset, and as a result we're left with some
> residual x/y offsets. Finally, if required by the hardware, we convert
> the remaining x/y offsets into a linear offset.
> 
> For gen2/3 we simply skip computing the final page offset, and just
> convert the src+fb x/y offsets directly into a linear offset since
> that's what the hardware wants.
> 
> After this all platforms, incluing SKL+, compute these things in exactly
> the same way (excluding alignemnt differences).
> 
> v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
>     plane src coordinates
>     Drop some spurious changes that got left behind during development
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Two comments below inline.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_gem_gtt.c  |  66 ++----
>  drivers/gpu/drm/i915/i915_gem_gtt.h  |  14 +-
>  drivers/gpu/drm/i915/intel_display.c | 448 ++++++++++++++++++++++++-----------
>  drivers/gpu/drm/i915/intel_drv.h     |  32 ++-
>  drivers/gpu/drm/i915/intel_sprite.c  | 102 ++++----
>  5 files changed, 402 insertions(+), 260 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index bb95b86..98aee6c 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -3255,11 +3255,6 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
>  	unsigned int column, row;
>  	unsigned int src_idx;
>  
> -	if (!sg) {
> -		st->nents = 0;
> -		sg = st->sgl;
> -	}
> -
>  	for (column = 0; column < width; column++) {
>  		src_idx = stride * (height - 1) + column;
>  		for (row = 0; row < height; row++) {
> @@ -3280,16 +3275,14 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
>  }
>  
>  static struct sg_table *
> -intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
> +intel_rotate_fb_obj_pages(const struct intel_rotation_info *info,
>  			  struct drm_i915_gem_object *obj)
>  {
> -	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
> -	unsigned int size_pages_uv;
> +	unsigned int size = intel_rotation_info_size(info);
>  	struct sg_page_iter sg_iter;
>  	unsigned long i;
>  	dma_addr_t *page_addr_list;
>  	struct sg_table *st;
> -	unsigned int uv_start_page;
>  	struct scatterlist *sg;
>  	int ret = -ENOMEM;
>  
> @@ -3299,57 +3292,32 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
>  	if (!page_addr_list)
>  		return ERR_PTR(ret);
>  
> -	/* Account for UV plane with NV12. */
> -	if (rot_info->pixel_format == DRM_FORMAT_NV12)
> -		size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
> -	else
> -		size_pages_uv = 0;
> -
>  	/* Allocate target SG list. */
>  	st = kmalloc(sizeof(*st), GFP_KERNEL);
>  	if (!st)
>  		goto err_st_alloc;
>  
> -	ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
> +	ret = sg_alloc_table(st, size, GFP_KERNEL);
>  	if (ret)
>  		goto err_sg_alloc;
>  
>  	/* Populate source page list from the object. */
>  	i = 0;
>  	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
> -		page_addr_list[i] = sg_page_iter_dma_address(&sg_iter);
> -		i++;
> +		page_addr_list[i++] = sg_page_iter_dma_address(&sg_iter);
>  	}
>  
> -	/* Rotate the pages. */
> -	sg = rotate_pages(page_addr_list, 0,
> -		     rot_info->width_pages, rot_info->height_pages,
> -		     rot_info->width_pages,
> -		     st, NULL);
> +	st->nents = 0;
> +	sg = st->sgl;
>  
> -	/* Append the UV plane if NV12. */
> -	if (rot_info->pixel_format == DRM_FORMAT_NV12) {
> -		uv_start_page = size_pages;
> -
> -		/* Check for tile-row un-alignment. */
> -		if (offset_in_page(rot_info->uv_offset))
> -			uv_start_page--;
> -
> -		rot_info->uv_start_page = uv_start_page;
> -
> -		rotate_pages(page_addr_list, uv_start_page,
> -			     rot_info->width_pages_uv,
> -			     rot_info->height_pages_uv,
> -			     rot_info->width_pages_uv,
> -			     st, sg);
> +	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++) {
> +		sg = rotate_pages(page_addr_list, info->plane[i].offset,
> +				  info->plane[i].width, info->plane[i].height,
> +				  info->plane[i].stride, st, sg);
>  	}
>  
> -	DRM_DEBUG_KMS(
> -		      "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
> -		      obj->base.size, rot_info->pitch, rot_info->height,
> -		      rot_info->pixel_format, rot_info->width_pages,
> -		      rot_info->height_pages, size_pages + size_pages_uv,
> -		      size_pages);
> +	DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages)\n",
> +		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
>  
>  	drm_free_large(page_addr_list);
>  
> @@ -3360,12 +3328,8 @@ err_sg_alloc:
>  err_st_alloc:
>  	drm_free_large(page_addr_list);
>  
> -	DRM_DEBUG_KMS(
> -		      "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
> -		      obj->base.size, ret, rot_info->pitch, rot_info->height,
> -		      rot_info->pixel_format, rot_info->width_pages,
> -		      rot_info->height_pages, size_pages + size_pages_uv,
> -		      size_pages);
> +	DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
> +		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
>  	return ERR_PTR(ret);
>  }
>  
> @@ -3516,7 +3480,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
>  	if (view->type == I915_GGTT_VIEW_NORMAL) {
>  		return obj->base.size;
>  	} else if (view->type == I915_GGTT_VIEW_ROTATED) {
> -		return view->rotated.size;
> +		return intel_rotation_info_size(&view->rotated) << PAGE_SHIFT;
>  	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
>  		return view->partial.size << PAGE_SHIFT;
>  	} else {
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index 68de734..ea28f7d 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -136,16 +136,10 @@ enum i915_ggtt_view_type {
>  };
>  
>  struct intel_rotation_info {
> -	unsigned int height;
> -	unsigned int pitch;
> -	unsigned int uv_offset;
> -	uint32_t pixel_format;
> -	uint64_t fb_modifier;
> -	unsigned int width_pages, height_pages;
> -	uint64_t size;
> -	unsigned int width_pages_uv, height_pages_uv;
> -	uint64_t size_uv;
> -	unsigned int uv_start_page;
> +	struct {
> +		/* tiles */
> +		unsigned int width, height, stride, offset;
> +	} plane[2];
>  };
>  
>  struct i915_ggtt_view {
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 028dc4a..0dcb710 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2274,49 +2274,28 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
>  	return ALIGN(height, tile_height);
>  }
>  
> -static int
> +unsigned int intel_rotation_info_size(const struct intel_rotation_info *info)
> +{
> +	unsigned int size = 0;
> +	int i;
> +
> +	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++)
> +		size += info->plane[i].width * info->plane[i].height;
> +
> +	return size;
> +}
> +
> +static void
>  intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
>  			const struct drm_framebuffer *fb,
>  			unsigned int rotation)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(fb->dev);
> -	struct intel_rotation_info *info = &view->rotated;
> -	unsigned int tile_size, tile_width, tile_height, cpp;
> -
> -	*view = i915_ggtt_view_normal;
> -
> -	if (!intel_rotation_90_or_270(rotation))
> -		return 0;
> -
> -	*view = i915_ggtt_view_rotated;
> -
> -	info->height = fb->height;
> -	info->pixel_format = fb->pixel_format;
> -	info->pitch = fb->pitches[0];
> -	info->uv_offset = fb->offsets[1];
> -	info->fb_modifier = fb->modifier[0];
> -
> -	tile_size = intel_tile_size(dev_priv);
> -
> -	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> -	tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
> -	tile_height = tile_size / tile_width;
> -
> -	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
> -	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
> -	info->size = info->width_pages * info->height_pages * tile_size;
> -
> -	if (info->pixel_format == DRM_FORMAT_NV12) {
> -		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
> -		tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
> -		tile_height = tile_size / tile_width;
> -
> -		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
> -		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
> -		info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
> +	if (intel_rotation_90_or_270(rotation)) {
> +		*view = i915_ggtt_view_rotated;
> +		view->rotated = to_intel_framebuffer(fb)->info;
> +	} else {
> +		*view = i915_ggtt_view_normal;
>  	}
> -
> -	return 0;
>  }
>  
>  static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
> @@ -2368,9 +2347,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
>  
>  	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
>  
> -	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
> -	if (ret)
> -		return ret;
> +	intel_fill_fb_ggtt_view(&view, fb, rotation);
>  
>  	/* Note that the w/a also requires 64 PTE of padding following the
>  	 * bo. We currently fill all unused PTE with the shadow page and so
> @@ -2433,18 +2410,31 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation
>  {
>  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>  	struct i915_ggtt_view view;
> -	int ret;
>  
>  	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
>  
> -	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
> -	WARN_ONCE(ret, "Couldn't get view from plane state!");
> +	intel_fill_fb_ggtt_view(&view, fb, rotation);
>  
>  	i915_gem_object_unpin_fence(obj);
>  	i915_gem_object_unpin_from_display_plane(obj, &view);
>  }
>  
>  /*
> + * Convert the x/y offsets into a linear offset.
> + * Only valid with 0/180 degree rotation, which is fine since linear
> + * offset is only used with linear buffers on pre-hsw and tiled buffers
> + * with gen2/3, and 90/270 degree rotations isn't supported on any of them.
> + */
> +unsigned int intel_fb_xy_to_linear(int x, int y,
> +				   const struct drm_framebuffer *fb, int plane)
> +{
> +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> +	unsigned int pitch = fb->pitches[plane];
> +
> +	return y * pitch + x * cpp;
> +}
> +
> +/*
>   * Return the tile dimensions in pixel units matching
>   * the specified rotation angle.
>   */
> @@ -2475,6 +2465,55 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
>  }
>  
>  /*
> + * Add the x/y offsets derived from fb->offsets[] to the user
> + * specified plane src x/y offsets. The resulting x/y offsets
> + * specify the start of scanout from the beginning of the gtt mapping.
> + */
> +void intel_add_fb_offsets(int *x, int *y,
> +			  const struct drm_framebuffer *fb, int plane,
> +			  unsigned int rotation)
> +
> +{
> +	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> +	const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> +	unsigned int pitch;
> +
> +	if (intel_rotation_90_or_270(rotation)) {
> +		pitch = intel_fb->plane[plane].rotated.pitch;
> +
> +		*x += intel_fb->plane[plane].rotated.x;
> +		*y += intel_fb->plane[plane].rotated.y;
> +	} else {
> +		pitch = fb->pitches[plane];
> +
> +		*x += intel_fb->plane[plane].normal.x;
> +		*y += intel_fb->plane[plane].normal.y;
> +	}
> +
> +	/* minimize x */
> +	if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
> +		unsigned int tile_size, tile_width, tile_height;
> +
> +		tile_size = intel_tile_size(dev_priv);
> +		tile_width = intel_tile_width(dev_priv, fb->modifier[plane], cpp);
> +		tile_height = tile_size / tile_width;
> +
> +		intel_rotate_tile_dims(&tile_width, &tile_height,
> +				       &pitch, cpp, rotation);
> +
> +		*y += *x / pitch * tile_height;
> +		*x  = *x % pitch;
> +	} else {
> +		/* in pixels */
> +		pitch /= cpp;
> +
> +		*y += *x / pitch;
> +		*x  = *x % pitch;
> +	}

This is called before we do the entire page_offset dance, so I don't think
we need a special case for tiled vs. untiled.
-Daniel

> +}
> +
> +/*
>   * Adjust the page offset by moving the difference into
>   * the x/y offsets.
>   *
> @@ -2514,20 +2553,23 @@ static void intel_adjust_page_offset(int *x, int *y,
>   * In the 90/270 rotated case, x and y are assumed
>   * to be already rotated to match the rotated GTT view, and
>   * pitch is the tile_height aligned framebuffer height.
> + *
> + * This function is used when computing the derived information
> + * under intel_framebuffer, so using any of that information
> + * here is not allowed. Anything under drm_framebuffer can be
> + * used. This is why the user has to pass in the pitch since it
> + * is specified in the rotated orientation.
>   */
> -unsigned long intel_compute_page_offset(int *x, int *y,
> -					const struct drm_framebuffer *fb, int plane,
> -					unsigned int pitch,
> -					unsigned int rotation)
> +static unsigned int _intel_compute_page_offset(const struct drm_i915_private *dev_priv,
> +					       int *x, int *y,
> +					       const struct drm_framebuffer *fb, int plane,
> +					       unsigned int pitch,
> +					       unsigned int rotation,
> +					       unsigned int alignment)
>  {
> -	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
>  	uint64_t fb_modifier = fb->modifier[plane];
>  	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> -	unsigned int offset, alignment;
> -
> -	alignment = intel_surf_alignment(dev_priv, fb_modifier);
> -	if (alignment)
> -		alignment--;
> +	unsigned int offset;
>  
>  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
>  		unsigned int tile_size, tile_width, tile_height;
> @@ -2560,6 +2602,145 @@ unsigned long intel_compute_page_offset(int *x, int *y,
>  	return offset & ~alignment;
>  }
>  
> +unsigned int intel_compute_page_offset(int *x, int *y,
> +				       const struct drm_framebuffer *fb, int plane,
> +				       unsigned int pitch,
> +				       unsigned int rotation)
> +{
> +	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> +	unsigned int alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
> +
> +	return _intel_compute_page_offset(dev_priv, x, y, fb, plane, pitch,
> +					  rotation, alignment ? (alignment - 1) : 0);
> +}
> +
> +/* Convert the fb->offset[] linear offset into x/y offsets */
> +static void intel_fb_offset_to_xy(int *x, int *y,
> +				  const struct drm_framebuffer *fb, int plane)
> +{
> +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> +	unsigned int pitch = fb->pitches[plane];
> +	unsigned int linear_offset = fb->offsets[plane];
> +
> +	*y = linear_offset / pitch;
> +	*x = linear_offset % pitch / cpp;
> +}
> +
> +static int
> +intel_fill_fb_info(struct drm_i915_private *dev_priv,
> +		   struct drm_framebuffer *fb)
> +{
> +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> +	struct intel_rotation_info *info = &intel_fb->info;
> +	unsigned int tile_size;
> +	unsigned int gtt_offset_rotated = 0;
> +	unsigned int max_size = 0;
> +	uint32_t format = fb->pixel_format;
> +	int i, num_planes = drm_format_num_planes(format);
> +
> +	tile_size = intel_tile_size(dev_priv);
> +
> +	for (i = 0; i < num_planes; i++) {
> +		unsigned int width, height;
> +		unsigned int cpp, offset, size;
> +		int x, y;
> +
> +		cpp = drm_format_plane_cpp(format, i);
> +		width = drm_format_plane_width(fb->width, format, i);
> +		height = drm_format_plane_height(fb->height, format, i);
> +
> +		intel_fb_offset_to_xy(&x, &y, fb, i);
> +
> +		/*
> +		 * First pixel of the framebuffer from
> +		 * the start of the normal gtt mapping.
> +		 */
> +		intel_fb->plane[i].normal.x = x;
> +		intel_fb->plane[i].normal.y = y;
> +
> +		offset = _intel_compute_page_offset(dev_priv, &x, &y,
> +						    fb, 0, fb->pitches[i],
> +						    BIT(DRM_ROTATE_0),
> +						    tile_size);
> +		offset /= tile_size;
> +		DRM_DEBUG("page offset %u pages\n", offset);
> +
> +		if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
> +			unsigned int tile_width, tile_height;
> +			unsigned int pitch;
> +			struct drm_rect r;
> +
> +			tile_width = intel_tile_width(dev_priv, fb->modifier[i], cpp);
> +			tile_height = tile_size / tile_width;
> +
> +			info->plane[i].offset = offset;
> +			info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width);
> +			info->plane[i].width = DIV_ROUND_UP((x + width) * cpp, tile_width);
> +			info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
> +
> +
> +			intel_fb->plane[i].rotated.pitch =
> +				info->plane[i].height * tile_height;
> +
> +			/* how many tiles does this plane need */
> +			size = info->plane[i].stride * info->plane[i].height;
> +			/*
> +			 * If the plane isn't horizontally tile aligned,
> +			 * we need one more tile.
> +			 */
> +			if (x != 0)
> +				size++;
> +
> +			pitch = intel_fb->plane[i].rotated.pitch;
> +
> +			/* rotate the x/y offsets to match the GTT view */
> +			r.x1 = x;
> +			r.y1 = y;
> +			r.x2 = x + width;
> +			r.y2 = y + height;
> +			drm_rect_rotate(&r, width, pitch, BIT(DRM_ROTATE_270));
> +			x = r.x1;
> +			y = r.y1;
> +
> +			intel_rotate_tile_dims(&tile_width, &tile_height, &pitch,
> +					       cpp, BIT(DRM_ROTATE_270));
> +
> +			/*
> +			 * We only keep the x/y offsets, so push all of the
> +			 * gtt offset into the x/y offsets.
> +			 */
> +			intel_adjust_page_offset(&x, &y, tile_width, tile_height,
> +						 tile_size, pitch,
> +						 gtt_offset_rotated * tile_size, 0);
> +
> +			gtt_offset_rotated += info->plane[i].width * info->plane[i].height;
> +
> +			/*
> +			 * First pixel of the framebuffer from
> +			 * the start of the rotated gtt mapping.
> +			 */
> +			intel_fb->plane[i].rotated.x = x;
> +			intel_fb->plane[i].rotated.y = y;
> +		} else {
> +			size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
> +					    x * cpp, tile_size);
> +		}
> +		DRM_DEBUG("%d offset %u, size %u, stride %u, height %u\n",
> +			  i, offset, size, info->plane[i].stride, info->plane[i].height);
> +
> +		/* how many tiles in total needed in the bo */
> +		max_size = max(max_size, offset + size);
> +	}
> +
> +	if (max_size * tile_size > to_intel_framebuffer(fb)->obj->base.size) {
> +		DRM_DEBUG("fb too big for bo (need %u bytes, have %zu bytes)\n",
> +			  max_size * tile_size, to_intel_framebuffer(fb)->obj->base.size);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  static int i9xx_format_to_fourcc(int format)
>  {
>  	switch (format) {
> @@ -2761,7 +2942,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  	struct drm_i915_gem_object *obj;
>  	int plane = intel_crtc->plane;
>  	unsigned int rotation;
> -	unsigned long linear_offset;
> +	unsigned int linear_offset;
>  	u32 dspcntr;
>  	u32 reg = DSPCNTR(plane);
>  	int pixel_size;
> @@ -2839,30 +3020,25 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  	if (IS_G4X(dev))
>  		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
>  
> -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
>  
> -	if (INTEL_INFO(dev)->gen >= 4) {
> +	if (INTEL_INFO(dev)->gen >= 4)
>  		intel_crtc->dspaddr_offset =
>  			intel_compute_page_offset(&x, &y, fb, 0,
>  						  fb->pitches[0], rotation);
> -		linear_offset -= intel_crtc->dspaddr_offset;
> -	} else {
> -		intel_crtc->dspaddr_offset = linear_offset;
> -	}
>  
>  	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
>  		dspcntr |= DISPPLANE_ROTATE_180;
>  
>  		x += (intel_crtc->config->pipe_src_w - 1);
>  		y += (intel_crtc->config->pipe_src_h - 1);
> -
> -		/* Finding the last pixel of the last line of the display
> -		data and adding to linear_offset*/
> -		linear_offset +=
> -			(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
> -			(intel_crtc->config->pipe_src_w - 1) * pixel_size;
>  	}
>  
> +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> +
> +	if (INTEL_INFO(dev)->gen < 4)
> +		intel_crtc->dspaddr_offset = linear_offset;
> +
>  	intel_crtc->adjusted_x = x;
>  	intel_crtc->adjusted_y = y;
>  
> @@ -2871,7 +3047,8 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
>  	if (INTEL_INFO(dev)->gen >= 4) {
>  		I915_WRITE(DSPSURF(plane),
> -			   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
> +			   intel_surf_gtt_offset(fb, 0, rotation) +
> +			   intel_crtc->dspaddr_offset);
>  		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
>  		I915_WRITE(DSPLINOFF(plane), linear_offset);
>  	} else
> @@ -2891,7 +3068,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  	struct drm_i915_gem_object *obj;
>  	int plane = intel_crtc->plane;
>  	unsigned int rotation;
> -	unsigned long linear_offset;
> +	unsigned int linear_offset;
>  	u32 dspcntr;
>  	u32 reg = DSPCNTR(plane);
>  	int pixel_size;
> @@ -2946,26 +3123,22 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  	if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
>  		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
>  
> -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
>  	intel_crtc->dspaddr_offset =
>  		intel_compute_page_offset(&x, &y, fb, 0,
>  					  fb->pitches[0], rotation);
> -	linear_offset -= intel_crtc->dspaddr_offset;
> +
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		dspcntr |= DISPPLANE_ROTATE_180;
>  
>  		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
>  			x += (intel_crtc->config->pipe_src_w - 1);
>  			y += (intel_crtc->config->pipe_src_h - 1);
> -
> -			/* Finding the last pixel of the last line of the display
> -			data and adding to linear_offset*/
> -			linear_offset +=
> -				(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
> -				(intel_crtc->config->pipe_src_w - 1) * pixel_size;
>  		}
>  	}
>  
> +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> +
>  	intel_crtc->adjusted_x = x;
>  	intel_crtc->adjusted_y = y;
>  
> @@ -2973,7 +3146,8 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  
>  	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
>  	I915_WRITE(DSPSURF(plane),
> -		   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
> +		   intel_surf_gtt_offset(fb, 0, rotation) +
> +		   intel_crtc->dspaddr_offset);
>  	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
>  		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
>  	} else {
> @@ -3000,30 +3174,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
>  	}
>  }
>  
> -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
> -				     struct drm_i915_gem_object *obj,
> -				     unsigned int plane)
> +unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
> +				   unsigned int rotation)

If you want to frob the interface, then I'd replace the fb and rotation
with the plane state.

>  {
> -	const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
> -	struct i915_vma *vma;
> -	unsigned char *offset;
> +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> +	struct i915_ggtt_view view;
>  
> -	if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
> -		view = &i915_ggtt_view_rotated;
> +	intel_fill_fb_ggtt_view(&view, fb, rotation);
>  
> -	vma = i915_gem_obj_to_ggtt_view(obj, view);
> -	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
> -		view->type))
> -		return -1;
> -
> -	offset = (unsigned char *)vma->node.start;
> -
> -	if (plane == 1) {
> -		offset += vma->ggtt_view.rotated.uv_start_page *
> -			  PAGE_SIZE;
> -	}
> -
> -	return (unsigned long)offset;
> +	return i915_gem_obj_ggtt_offset_view(obj, &view);
>  }
>  
>  static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
> @@ -3142,18 +3301,16 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct drm_plane *plane = crtc->primary;
> +	struct intel_framebuffer *intel_fb;
>  	bool visible = to_intel_plane_state(plane->state)->visible;
> -	struct drm_i915_gem_object *obj;
>  	int pipe = intel_crtc->pipe;
>  	u32 plane_ctl, stride_div, stride;
> -	u32 tile_height, plane_offset, plane_size;
>  	unsigned int rotation;
> -	int x_offset, y_offset;
>  	unsigned long surf_addr;
>  	struct intel_crtc_state *crtc_state = intel_crtc->config;
>  	struct intel_plane_state *plane_state;
> -	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
> -	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
> +	int src_w, src_h;
> +	int dst_x, dst_y, dst_w, dst_h;
>  	int scaler_id = -1;
>  	int pixel_size;
>  
> @@ -3166,6 +3323,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  		return;
>  	}
>  
> +	intel_fb = to_intel_framebuffer(fb);
>  	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  
>  	plane_ctl = PLANE_CTL_ENABLE |
> @@ -3179,16 +3337,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  	rotation = plane->state->rotation;
>  	plane_ctl |= skl_plane_ctl_rotation(rotation);
>  
> -	obj = intel_fb_obj(fb);
> -	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> -					       fb->pixel_format);
> -	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
> -
> -	WARN_ON(drm_rect_width(&plane_state->src) == 0);
> -
>  	scaler_id = plane_state->scaler_id;
> -	src_x = plane_state->src.x1 >> 16;
> -	src_y = plane_state->src.y1 >> 16;
>  	src_w = drm_rect_width(&plane_state->src) >> 16;
>  	src_h = drm_rect_height(&plane_state->src) >> 16;
>  	dst_x = plane_state->dst.x1;
> @@ -3196,31 +3345,48 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  	dst_w = drm_rect_width(&plane_state->dst);
>  	dst_h = drm_rect_height(&plane_state->dst);
>  
> -	WARN_ON(x != src_x || y != src_y);
> -
>  	if (intel_rotation_90_or_270(rotation)) {
> -		/* stride = Surface height in tiles */
> -		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> -						pixel_size);
> -		stride = DIV_ROUND_UP(fb->height, tile_height);
> -		x_offset = stride * tile_height - y - src_h;
> -		y_offset = x;
> -		plane_size = (src_w - 1) << 16 | (src_h - 1);
> +		struct drm_rect r = {
> +			.x1 = x,
> +			.x2 = x + src_w,
> +			.y1 = y,
> +			.y2 = y + src_h,
> +		};
> +
> +		/* Rotate src coordinates to match rotated GTT view */
> +		drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
> +
> +		x = r.x1;
> +		y = r.y1;
> +		src_w = drm_rect_width(&r);
> +		src_h = drm_rect_height(&r);
> +
> +		stride_div = intel_tile_height(dev_priv, fb->modifier[0],
> +					       pixel_size);
> +		stride = intel_fb->plane[0].rotated.pitch;
>  	} else {
> -		stride = fb->pitches[0] / stride_div;
> -		x_offset = x;
> -		y_offset = y;
> -		plane_size = (src_h - 1) << 16 | (src_w - 1);
> +		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> +						       fb->pixel_format);
> +		stride = fb->pitches[0];
>  	}
> -	plane_offset = y_offset << 16 | x_offset;
>  
> -	intel_crtc->adjusted_x = x_offset;
> -	intel_crtc->adjusted_y = y_offset;
> +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> +	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> +					      stride, rotation);
> +
> +	/* Sizes are 0 based */
> +	src_w--;
> +	src_h--;
> +	dst_w--;
> +	dst_h--;
> +
> +	intel_crtc->adjusted_x = x;
> +	intel_crtc->adjusted_y = y;
>  
>  	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
> -	I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
> -	I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
> -	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
> +	I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
> +	I915_WRITE(PLANE_STRIDE(pipe, 0), stride / stride_div);
> +	I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w);
>  
>  	if (scaler_id >= 0) {
>  		uint32_t ps_ctrl = 0;
> @@ -3237,7 +3403,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  		I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);
>  	}
>  
> -	I915_WRITE(PLANE_SURF(pipe, 0), surf_addr);
> +	I915_WRITE(PLANE_SURF(pipe, 0),
> +		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
>  
>  	POSTING_READ(PLANE_SURF(pipe, 0));
>  }
> @@ -11521,8 +11688,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
>  	if (ret)
>  		goto cleanup_pending;
>  
> -	work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
> -						  obj, 0);
> +	work->gtt_offset = intel_surf_gtt_offset(fb, 0, primary->state->rotation);
>  	work->gtt_offset += intel_crtc->dspaddr_offset;
>  
>  	if (mmio_flip) {
> @@ -14319,7 +14485,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  				  struct drm_i915_gem_object *obj)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	unsigned int aligned_height;
>  	int ret;
>  	u32 pitch_limit, stride_alignment;
>  
> @@ -14443,16 +14608,13 @@ static int intel_framebuffer_init(struct drm_device *dev,
>  	if (ret)
>  		return ret;
>  
> -	aligned_height = intel_fb_align_height(dev, mode_cmd->height,
> -					       mode_cmd->pixel_format,
> -					       mode_cmd->modifier[0]);
> -	/* FIXME drm helper for size checks (especially planar formats)? */
> -	if (obj->base.size < aligned_height * mode_cmd->pitches[0])
> -		return -EINVAL;
> -
>  	drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
>  	intel_fb->obj = obj;
>  
> +	ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
> +	if (ret)
> +		return ret;
> +
>  	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
>  	if (ret) {
>  		DRM_ERROR("framebuffer init failed %d\n", ret);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 36d049d..395afd3 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -118,6 +118,19 @@ enum intel_output_type {
>  struct intel_framebuffer {
>  	struct drm_framebuffer base;
>  	struct drm_i915_gem_object *obj;
> +	struct intel_rotation_info info;
> +
> +	struct {
> +		struct {
> +			/* pixels */
> +			unsigned int x, y;
> +		} normal;
> +		struct {
> +			/* pixels */
> +			unsigned int x, y;
> +			unsigned int pitch;
> +		} rotated;
> +	} plane[2];
>  };
>  
>  struct intel_fbdev {
> @@ -1028,6 +1041,12 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv);
>  void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
>  
>  /* intel_display.c */
> +unsigned int intel_rotation_info_size(const struct intel_rotation_info *info);
> +unsigned int intel_fb_xy_to_linear(int x, int y,
> +				   const struct drm_framebuffer *fb, int plane);
> +void intel_add_fb_offsets(int *x, int *y,
> +			  const struct drm_framebuffer *fb, int plane,
> +			  unsigned int rotation);
>  extern const struct drm_plane_funcs intel_plane_funcs;
>  bool intel_has_pending_fb_unpin(struct drm_device *dev);
>  int intel_pch_rawclk(struct drm_device *dev);
> @@ -1134,10 +1153,10 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
>  void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
>  #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
>  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
> -unsigned long intel_compute_page_offset(int *x, int *y,
> -					const struct drm_framebuffer *fb, int plane,
> -					unsigned int pitch,
> -					unsigned int rotation);
> +unsigned int intel_compute_page_offset(int *x, int *y,
> +				       const struct drm_framebuffer *fb, int plane,
> +				       unsigned int pitch,
> +				       unsigned int rotation);
>  void intel_prepare_reset(struct drm_device *dev);
>  void intel_finish_reset(struct drm_device *dev);
>  void hsw_enable_pc8(struct drm_i915_private *dev_priv);
> @@ -1174,9 +1193,8 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
>  int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
>  int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
>  
> -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
> -				     struct drm_i915_gem_object *obj,
> -				     unsigned int plane);
> +unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
> +				   unsigned int rotation);
>  
>  u32 skl_plane_ctl_format(uint32_t pixel_format);
>  u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 828c3eb..d9d37b0 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -188,17 +188,15 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  	struct drm_device *dev = drm_plane->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
> -	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
>  	const int pipe = intel_plane->pipe;
>  	const int plane = intel_plane->plane + 1;
>  	u32 plane_ctl, stride_div, stride;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  	const struct drm_intel_sprite_colorkey *key =
>  		&to_intel_plane_state(drm_plane->state)->ckey;
> -	unsigned long surf_addr;
> -	u32 tile_height, plane_offset, plane_size;
> +	unsigned int surf_addr;
>  	unsigned int rotation;
> -	int x_offset, y_offset;
>  	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
>  	int scaler_id;
>  
> @@ -215,17 +213,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  				       pixel_size, true,
>  				       src_w != crtc_w || src_h != crtc_h);
>  
> -	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> -					       fb->pixel_format);
> -
>  	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
>  
> -	/* Sizes are 0 based */
> -	src_w--;
> -	src_h--;
> -	crtc_w--;
> -	crtc_h--;
> -
>  	if (key->flags) {
>  		I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
>  		I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
> @@ -237,27 +226,43 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  	else if (key->flags & I915_SET_COLORKEY_SOURCE)
>  		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
>  
> -	surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
> -
>  	if (intel_rotation_90_or_270(rotation)) {
> -		/* stride: Surface height in tiles */
> -		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> -						pixel_size);
> -		stride = DIV_ROUND_UP(fb->height, tile_height);
> -		plane_size = (src_w << 16) | src_h;
> -		x_offset = stride * tile_height - y - (src_h + 1);
> -		y_offset = x;
> +		struct drm_rect r = {
> +			.x1 = x,
> +			.x2 = x + src_w,
> +			.y1 = y,
> +			.y2 = y + src_h,
> +		};
> +
> +		/* Rotate src coordinates to match rotated GTT view */
> +		drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
> +
> +		x = r.x1;
> +		y = r.y1;
> +		src_w = drm_rect_width(&r);
> +		src_h = drm_rect_height(&r);
> +
> +		stride_div = intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
> +		stride = intel_fb->plane[0].rotated.pitch;
>  	} else {
> -		stride = fb->pitches[0] / stride_div;
> -		plane_size = (src_h << 16) | src_w;
> -		x_offset = x;
> -		y_offset = y;
> +		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> +						       fb->pixel_format);
> +		stride = fb->pitches[0];
>  	}
> -	plane_offset = y_offset << 16 | x_offset;
>  
> -	I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
> -	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
> -	I915_WRITE(PLANE_SIZE(pipe, plane), plane_size);
> +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> +	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> +					      stride, rotation);
> +
> +	/* Sizes are 0 based */
> +	src_w--;
> +	src_h--;
> +	crtc_w--;
> +	crtc_h--;
> +
> +	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
> +	I915_WRITE(PLANE_STRIDE(pipe, plane), stride / stride_div);
> +	I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
>  
>  	/* program plane scaler */
>  	if (scaler_id >= 0) {
> @@ -279,7 +284,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  	}
>  
>  	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
> -	I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
> +	I915_WRITE(PLANE_SURF(pipe, plane),
> +		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
>  	POSTING_READ(PLANE_SURF(pipe, plane));
>  }
>  
> @@ -355,8 +361,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	int plane = intel_plane->plane;
>  	u32 sprctl;
>  	unsigned int rotation = dplane->state->rotation;
> -	unsigned long sprsurf_offset, linear_offset;
> -	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> +	unsigned int sprsurf_offset, linear_offset;
>  	const struct drm_intel_sprite_colorkey *key =
>  		&to_intel_plane_state(dplane->state)->ckey;
>  
> @@ -420,19 +425,19 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	crtc_w--;
>  	crtc_h--;
>  
> -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
>  	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
>  						   fb->pitches[0], rotation);
> -	linear_offset -= sprsurf_offset;
>  
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		sprctl |= SP_ROTATE_180;
>  
>  		x += src_w;
>  		y += src_h;
> -		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
>  	}
>  
> +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> +
>  	if (key->flags) {
>  		I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
>  		I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
> @@ -457,8 +462,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  
>  	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
>  	I915_WRITE(SPCNTR(pipe, plane), sprctl);
> -	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
> -		   sprsurf_offset);
> +	I915_WRITE(SPSURF(pipe, plane),
> +		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
>  	POSTING_READ(SPSURF(pipe, plane));
>  }
>  
> @@ -492,7 +497,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	enum pipe pipe = intel_plane->pipe;
>  	u32 sprctl, sprscale = 0;
>  	unsigned int rotation = plane->state->rotation;
> -	unsigned long sprsurf_offset, linear_offset;
> +	unsigned int sprsurf_offset, linear_offset;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  	const struct drm_intel_sprite_colorkey *key =
>  		&to_intel_plane_state(plane->state)->ckey;
> @@ -552,10 +557,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	if (crtc_w != src_w || crtc_h != src_h)
>  		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
>  
> -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
>  	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
>  						   fb->pitches[0], rotation);
> -	linear_offset -= sprsurf_offset;
>  
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		sprctl |= SPRITE_ROTATE_180;
> @@ -564,11 +568,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
>  			x += src_w;
>  			y += src_h;
> -			linear_offset += src_h * fb->pitches[0] +
> -				src_w * pixel_size;
>  		}
>  	}
>  
> +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> +
>  	if (key->flags) {
>  		I915_WRITE(SPRKEYVAL(pipe), key->min_value);
>  		I915_WRITE(SPRKEYMAX(pipe), key->max_value);
> @@ -597,7 +601,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		I915_WRITE(SPRSCALE(pipe), sprscale);
>  	I915_WRITE(SPRCTL(pipe), sprctl);
>  	I915_WRITE(SPRSURF(pipe),
> -		   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
> +		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
>  	POSTING_READ(SPRSURF(pipe));
>  }
>  
> @@ -632,7 +636,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
>  	int pipe = intel_plane->pipe;
>  	unsigned int rotation = plane->state->rotation;
> -	unsigned long dvssurf_offset, linear_offset;
> +	unsigned int dvssurf_offset, linear_offset;
>  	u32 dvscntr, dvsscale;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  	const struct drm_intel_sprite_colorkey *key =
> @@ -689,19 +693,19 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	if (crtc_w != src_w || crtc_h != src_h)
>  		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
>  
> -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
>  	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
>  						   fb->pitches[0], rotation);
> -	linear_offset -= dvssurf_offset;
>  
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		dvscntr |= DVS_ROTATE_180;
>  
>  		x += src_w;
>  		y += src_h;
> -		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
>  	}
>  
> +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> +
>  	if (key->flags) {
>  		I915_WRITE(DVSKEYVAL(pipe), key->min_value);
>  		I915_WRITE(DVSKEYMAX(pipe), key->max_value);
> @@ -725,7 +729,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  	I915_WRITE(DVSSCALE(pipe), dvsscale);
>  	I915_WRITE(DVSCNTR(pipe), dvscntr);
>  	I915_WRITE(DVSSURF(pipe),
> -		   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
> +		   intel_surf_gtt_offset(fb, 0, rotation) + dvssurf_offset);
>  	POSTING_READ(DVSSURF(pipe));
>  }
>  
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 22/22] drm/i915: Don't pass pitch to intel_compute_page_offset()
  2015-10-14 16:29 ` [PATCH 22/22] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
@ 2015-10-21 12:06   ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 12:06 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 07:29:14PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> intel_compute_page_offset() can dig up the correct pitch from the fb
> itself, no need for the caller to pass it in.
> 
> A bit of extra care is needed for the lower level
> _intel_compute_page_offset() since that one gets called before the
> rotated pitch under intel_fb is populated. Note that we don't actually
> call it with anything but DRM_ROTATE_0 there so we wouldn't actually
> look up the rotated pitch there, but still, leave the pitch as something
> the caller has to pass to _intel_compute_page_offset() as an
> indicator that something is a bit special.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 32 +++++++++++++++++---------------
>  drivers/gpu/drm/i915/intel_drv.h     |  1 -
>  drivers/gpu/drm/i915/intel_sprite.c  | 26 +++++++++++---------------
>  3 files changed, 28 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 8c7dc03..15dbe48 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2604,11 +2604,16 @@ static unsigned int _intel_compute_page_offset(const struct drm_i915_private *de
>  
>  unsigned int intel_compute_page_offset(int *x, int *y,
>  				       const struct drm_framebuffer *fb, int plane,
> -				       unsigned int pitch,
>  				       unsigned int rotation)

Maybe also just pass the plane state here?

>  {
>  	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
>  	unsigned int alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
> +	unsigned int pitch;
> +
> +	if (intel_rotation_90_or_270(rotation))
> +		pitch = to_intel_framebuffer(fb)->plane[plane].rotated.pitch;
> +	else
> +		pitch = fb->pitches[plane];
>  
>  	return _intel_compute_page_offset(dev_priv, x, y, fb, plane, pitch,
>  					  rotation, alignment ? (alignment - 1) : 0);
> @@ -3026,8 +3031,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
>  
>  	if (INTEL_INFO(dev)->gen >= 4)
>  		intel_crtc->dspaddr_offset =
> -			intel_compute_page_offset(&x, &y, fb, 0,
> -						  fb->pitches[0], rotation);
> +			intel_compute_page_offset(&x, &y, fb, 0, rotation);
>  
>  	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
>  		dspcntr |= DISPPLANE_ROTATE_180;
> @@ -3129,8 +3133,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
>  
>  	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
>  	intel_crtc->dspaddr_offset =
> -		intel_compute_page_offset(&x, &y, fb, 0,
> -					  fb->pitches[0], rotation);
> +		intel_compute_page_offset(&x, &y, fb, 0, rotation);
>  
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		dspcntr |= DISPPLANE_ROTATE_180;
> @@ -3308,7 +3311,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  	struct intel_framebuffer *intel_fb;
>  	bool visible = to_intel_plane_state(plane->state)->visible;
>  	int pipe = intel_crtc->pipe;
> -	u32 plane_ctl, stride_div, stride;
> +	u32 plane_ctl, stride;
>  	unsigned int rotation;
>  	unsigned long surf_addr;
>  	struct intel_crtc_state *crtc_state = intel_crtc->config;
> @@ -3365,18 +3368,17 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  		src_w = drm_rect_width(&r);
>  		src_h = drm_rect_height(&r);
>  
> -		stride_div = intel_tile_height(dev_priv, fb->modifier[0],
> -					       pixel_size);
> -		stride = intel_fb->plane[0].rotated.pitch;
> +		stride = intel_fb->plane[0].rotated.pitch /

I'd go with two lines here and

		stride /= intel_tile_height(dev_priv, fb->modifier[0],
					    pixel_size);

Same below. And commit message fails to mention this unrelated color
change.

With that addressed: Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  	} else {
> -		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> -						       fb->pixel_format);
> -		stride = fb->pitches[0];
> +		stride = fb->pitches[0] /
> +			intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> +						  fb->pixel_format);
>  	}
>  
>  	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> -	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> -					      stride, rotation);
> +	surf_addr = intel_compute_page_offset(&x, &y, fb, 0, rotation);
>  
>  	/* Sizes are 0 based */
>  	src_w--;
> @@ -3389,7 +3391,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  
>  	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
>  	I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
> -	I915_WRITE(PLANE_STRIDE(pipe, 0), stride / stride_div);
> +	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
>  	I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w);
>  
>  	if (scaler_id >= 0) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 395afd3..af9861a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1155,7 +1155,6 @@ void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
>  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
>  unsigned int intel_compute_page_offset(int *x, int *y,
>  				       const struct drm_framebuffer *fb, int plane,
> -				       unsigned int pitch,
>  				       unsigned int rotation);
>  void intel_prepare_reset(struct drm_device *dev);
>  void intel_finish_reset(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 552c01d..c4b7226 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -191,7 +191,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
>  	const int pipe = intel_plane->pipe;
>  	const int plane = intel_plane->plane + 1;
> -	u32 plane_ctl, stride_div, stride;
> +	u32 plane_ctl, stride;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
>  	const struct drm_intel_sprite_colorkey *key =
>  		&to_intel_plane_state(drm_plane->state)->ckey;
> @@ -242,17 +242,16 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  		src_w = drm_rect_width(&r);
>  		src_h = drm_rect_height(&r);
>  
> -		stride_div = intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
> -		stride = intel_fb->plane[0].rotated.pitch;
> +		stride = intel_fb->plane[0].rotated.pitch /
> +			intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
>  	} else {
> -		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> -						       fb->pixel_format);
> -		stride = fb->pitches[0];
> +		stride = fb->pitches[0] /
> +			intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> +						  fb->pixel_format);
>  	}
>  
>  	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> -	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> -					      stride, rotation);
> +	surf_addr = intel_compute_page_offset(&x, &y, fb, 0, rotation);
>  
>  	/* Sizes are 0 based */
>  	src_w--;
> @@ -261,7 +260,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  	crtc_h--;
>  
>  	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
> -	I915_WRITE(PLANE_STRIDE(pipe, plane), stride / stride_div);
> +	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
>  	I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
>  
>  	/* program plane scaler */
> @@ -426,8 +425,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
>  	crtc_h--;
>  
>  	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> -	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> -						   fb->pitches[0], rotation);
> +	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0, rotation);
>  
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		sprctl |= SP_ROTATE_180;
> @@ -558,8 +556,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
>  
>  	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> -	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> -						   fb->pitches[0], rotation);
> +	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0, rotation);
>  
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		sprctl |= SPRITE_ROTATE_180;
> @@ -694,8 +691,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
>  		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
>  
>  	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> -	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> -						   fb->pitches[0], rotation);
> +	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0, rotation);
>  
>  	if (rotation == BIT(DRM_ROTATE_180)) {
>  		dvscntr |= DVS_ROTATE_180;
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic
  2015-10-14 16:59 ` [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic Daniel Vetter
@ 2015-10-21 12:09   ` Daniel Vetter
  2015-10-21 15:15     ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 12:09 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 14, 2015 at 06:59:38PM +0200, Daniel Vetter wrote:
> On Wed, Oct 14, 2015 at 07:28:52PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > So while reviewing the NV12 stuff it became clear to me no one
> > had really given fb->offsets[] handling any serious thought.
> > So this patch series aims to fix that. We now treat fb->offsets[]
> > as a linear offset always. One clear benefit over treating it as
> > a linear offset as opposed to a raw byte offset is that we don't
> > have to think about the layout of bytes within the tile at all.
> > 
> > The series also generalizes the page rotation to be format agnostic,
> > the caller just specifies the desired geometry in pages for each
> > plane, and the rotation code builds up the sg. The intel_rotation_info
> > then just contains the minimal amount of information needed to
> > do the page rotation.
> > 
> > SKL+ also gets changed to use the compute_page_offset stuff so that
> > the plane SURF register will contain the closes (properly aligned)
> > page boundary, and the x/y offsets deal with whatever is left over.
> > The plane code for the other platforms also gets simpler in the end
> > I think. Also the 90/270 rotation handling becomes rather trivial
> > for the plane code.
> > 
> > I should still write some decent tests to exercise fb->offsets[].
> > 
> > Series available here:
> > git://github.com/vsyrjala/linux.git fb_offsets
> 
> As mentioned on irc patches 13&14 need to me unified with my 3 patch
> series, but otherwise lgtm overall.

Ok done a review pass and I think I unconfused myself about the bytes vs.
pixels fun. Imo that really needs to be a lot more explicit. My
suggestion:

- tile_width, tile_height, pixel_stride: always pixels
- tile_pitch, pitch: always bytes

And instead of silently changing units just use new variables. gcc will
clean it up. I'm totally ok with doing that as a follow-up.

I didn't review the 2nd last patch in detail since -ETOOBIG.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 03/22] drm/i915: Factor out intel_tile_width()
  2015-10-21 10:15   ` Daniel Vetter
@ 2015-10-21 12:09     ` Ville Syrjälä
  2015-10-21 12:16       ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 12:09 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 12:15:42PM +0200, Daniel Vetter wrote:
> On Wed, Oct 14, 2015 at 07:28:55PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Pull the tile width calculations from intel_fb_stride_alignment() into a
> > new function intel_tile_width().
> > 
> > Also take the opportunity to pass aroun dev_priv instead of dev to
> > intel_fb_stride_alignment().
> > 
> > v2: Reorder argumnents to be more consistent with other functions
> >     Change intel_fb_stride_alignment() to accept dev_priv instead of dev
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 76 +++++++++++++++++++++++-------------
> >  drivers/gpu/drm/i915/intel_drv.h     |  4 +-
> >  drivers/gpu/drm/i915/intel_sprite.c  |  2 +-
> >  3 files changed, 51 insertions(+), 31 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 6add8d1..c31fe47 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2214,6 +2214,41 @@ static bool need_vtd_wa(struct drm_device *dev)
> >  	return false;
> >  }
> >  
> > +static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
> > +				     uint64_t fb_modifier, unsigned int cpp)
> > +{
> > +	switch (fb_modifier) {
> > +	case DRM_FORMAT_MOD_NONE:
> > +		return cpp;
> > +	case I915_FORMAT_MOD_X_TILED:
> > +		return IS_GEN2(dev_priv) ? 128 : 512;
> > +	case I915_FORMAT_MOD_Y_TILED:
> > +		/* No need to check for old gens and Y tiling since this is
> > +		 * about the display engine and those will be blocked before
> > +		 * we get here.
> > +		 */
> > +		return 128;
> 
> Imo just drop the comment and change this to
> 
> 		return HAS_128_BYTE_Y_TILING(dev) 128 : 512;
> 
> Just to avoid wtf moments. It's less code than the comment too.

Yeah, can do. And we definitely need it if we want to use this for gem
stuff. Although we need to change HAS_128_BYTE_Y_TILING() to include
gen2. Currently that define actually means "has 128x32 Y tiling". Or
we make intel_tile_width() check for 'IS_GEN2 || HAS_128_BYTE_Y_TILING'.

> 
> Another one: Enforcing pot alignment for gen2/3 is fairly hapzardous - we
> do it accidentally by requiring that for X-tiled the underlying obj is
> also X-tiled and that strides match. Comment for this would be good here.
> 
> > +	case I915_FORMAT_MOD_Yf_TILED:
> > +		switch (cpp) {
> > +		case 1:
> > +			return 64;
> > +		case 2:
> > +		case 4:
> > +			return 128;
> 
> With 4 cpp we have 4x4 pixels for the 64b cacheline. So 8x8 for the 256b
> block with 1:1 aspect ratio, hence 64x64 pixel tile for the full page.

32x32 for the full page

> 
> > +		case 8:
> 
> With 8 cpp we have 2x4 pixels for the 64b cacheline. So 8x4 for the 256b
> block with 2:1 aspect ratio, hence 64x32 pixel tile for the full page.

32x16 for the full page

> 
> > +		case 16:
> > +			return 256;
> 
> With 16 cpp we have 1x4 pixels for the 64b cacheline. So 4x4 for the 256b
> block with 1:1 aspect ratio, hence 32x32 pixel tile for the full page.

16x16 for the full page

> 
> Otherwise looks good to me, Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> once we close the above.
> 
> Cheers, Daniel
> 
> > +		default:
> > +			MISSING_CASE(cpp);
> > +			return cpp;
> > +		}
> > +		break;
> > +	default:
> > +		MISSING_CASE(fb_modifier);
> > +		return cpp;
> > +	}
> > +}
> > +
> >  unsigned int
> >  intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
> >  		  uint64_t fb_format_modifier, unsigned int plane)
> > @@ -2895,37 +2930,20 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> >  	POSTING_READ(reg);
> >  }
> >  
> > -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
> > -			      uint32_t pixel_format)
> > +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> > +			      uint64_t fb_modifier, uint32_t pixel_format)
> >  {
> > -	u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
> > -
> >  	/*
> >  	 * The stride is either expressed as a multiple of 64 bytes
> >  	 * chunks for linear buffers or in number of tiles for tiled
> >  	 * buffers.
> >  	 */
> > -	switch (fb_modifier) {
> > -	case DRM_FORMAT_MOD_NONE:
> > -		return 64;
> > -	case I915_FORMAT_MOD_X_TILED:
> > -		if (INTEL_INFO(dev)->gen == 2)
> > -			return 128;
> > -		return 512;
> > -	case I915_FORMAT_MOD_Y_TILED:
> > -		/* No need to check for old gens and Y tiling since this is
> > -		 * about the display engine and those will be blocked before
> > -		 * we get here.
> > -		 */
> > -		return 128;
> > -	case I915_FORMAT_MOD_Yf_TILED:
> > -		if (bits_per_pixel == 8)
> > -			return 64;
> > -		else
> > -			return 128;
> > -	default:
> > -		MISSING_CASE(fb_modifier);
> > +	if (fb_modifier == DRM_FORMAT_MOD_NONE) {
> >  		return 64;
> > +	} else {
> > +		unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
> > +
> > +		return intel_tile_width(dev_priv, fb_modifier, cpp);
> >  	}
> >  }
> >  
> > @@ -3106,7 +3124,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
> >  	plane_ctl |= skl_plane_ctl_rotation(rotation);
> >  
> >  	obj = intel_fb_obj(fb);
> > -	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> > +	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> >  					       fb->pixel_format);
> >  	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
> >  
> > @@ -9066,7 +9084,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
> >  	fb->width = ((val >> 0) & 0x1fff) + 1;
> >  
> >  	val = I915_READ(PLANE_STRIDE(pipe, 0));
> > -	stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
> > +	stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> >  						fb->pixel_format);
> >  	fb->pitches[0] = (val & 0x3ff) * stride_mult;
> >  
> > @@ -11137,7 +11155,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
> >  	 * linear buffers or in number of tiles for tiled buffers.
> >  	 */
> >  	stride = fb->pitches[0] /
> > -		 intel_fb_stride_alignment(dev, fb->modifier[0],
> > +		 intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> >  					   fb->pixel_format);
> >  
> >  	/*
> > @@ -14214,6 +14232,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
> >  				  struct drm_mode_fb_cmd2 *mode_cmd,
> >  				  struct drm_i915_gem_object *obj)
> >  {
> > +	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	unsigned int aligned_height;
> >  	int ret;
> >  	u32 pitch_limit, stride_alignment;
> > @@ -14255,7 +14274,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
> >  		return -EINVAL;
> >  	}
> >  
> > -	stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
> > +	stride_alignment = intel_fb_stride_alignment(dev_priv,
> > +						     mode_cmd->modifier[0],
> >  						     mode_cmd->pixel_format);
> >  	if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
> >  		DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 1152566..98a8d31 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1017,8 +1017,8 @@ unsigned int intel_fb_align_height(struct drm_device *dev,
> >  				   uint64_t fb_format_modifier);
> >  void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire,
> >  			enum fb_op_origin origin);
> > -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
> > -			      uint32_t pixel_format);
> > +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> > +			      uint64_t fb_modifier, uint32_t pixel_format);
> >  
> >  /* intel_audio.c */
> >  void intel_init_audio(struct drm_device *dev);
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> > index 90e27c8..3d96871 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -215,7 +215,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> >  				       pixel_size, true,
> >  				       src_w != crtc_w || src_h != crtc_h);
> >  
> > -	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> > +	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> >  					       fb->pixel_format);
> >  
> >  	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
> > -- 
> > 2.4.9
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
  2015-10-21 11:36     ` Ville Syrjälä
@ 2015-10-21 12:11       ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 12:11 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 02:36:34PM +0300, Ville Syrjälä wrote:
> On Wed, Oct 21, 2015 at 12:53:34PM +0200, Daniel Vetter wrote:
> > On Wed, Oct 14, 2015 at 07:29:00PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > The page aligned surface address calculation needs to know which way
> > > things are rotated. The contract now says that the caller must pass the
> > > rotate x/y coordinates, as well as the tile_height aligned stride in
> > > the tile_height direction. This will make it fairly simple to deal with
> > > 90/270 degree rotation on SKL+ where we have to deal with the rotated
> > > view into the GTT.
> > > 
> > > v2: Pass rotation instead of bool even thoughwe only care about 0/180 vs. 90/270
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_display.c | 62 ++++++++++++++++++++++++++++++------
> > >  drivers/gpu/drm/i915/intel_drv.h     |  3 +-
> > >  drivers/gpu/drm/i915/intel_sprite.c  | 15 +++++----
> > >  3 files changed, 64 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index 75be66b..bd55d06 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -2451,13 +2451,50 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
> > >  	i915_gem_object_unpin_from_display_plane(obj, &view);
> > >  }
> > >  
> > > -/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
> > > - * is assumed to be a power-of-two. */
> > > +/*
> > > + * Return the tile dimensions in pixel units matching
> > > + * the specified rotation angle.
> > > + */
> > > +static void intel_rotate_tile_dims(unsigned int *tile_width,
> > > +				   unsigned int *tile_height,
> > > +				   unsigned int *pitch,
> > > +				   unsigned int cpp,
> > > +				   unsigned int rotation)
> > 
> > A rotation enum would be nice, so that we can employ sparse to check it.
> > That'd work since sparse treats enums as bitfields, but we'd need to
> > add names for the BIT(DRM_ROTATION_*) variants. Just an aside.
> 
> I was thinking of including the '1<<x' in the define already since the
> current thing just invites bugs all over. I guess making it an enum at
> the same time should be easy.
> 
> > 
> > > +{
> > > +	if (intel_rotation_90_or_270(rotation)) {
> > > +		WARN_ON(*pitch % *tile_height);
> > > +
> > > +		/* pixel units please */
> > > +		*tile_width /= cpp;
> > 
> > Ok, something dawns on me now about tile_width ... it's in bytes, I
> > somehow thought it's pixels. And this function doing a behind-the-scenes
> > conversions from bytes to pixels is a bit tricky.
> > 
> > Should we have separate tile_pitch and tile_width to unconfuse this?
> > Generally foo_width in the modeset code is mostly pixels ...
> 
> Yeah, things are a bit unclear with bytes vs. pixels sometimes. I
> usually think of tile width as bytes because then you don't have to
> consider the pixel format (well, except for Yf/Ys tiling), but here
> we want it in pixels instead.
> 
> I'm not sure tile_pitch is a good name becuse then it might get
> confused with the pitch for the fb or fence. But I don't really have
> a better name in mind either.

Yeah, redefining tile_width to be in pixel would break with existing code.
But silently converting from bytes to pixels is worse, and I don't have
any better idea than tile_width and tile_pitch for these two. We'd need to
update i915_gem_tiling too though for consistency.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 03/22] drm/i915: Factor out intel_tile_width()
  2015-10-21 12:09     ` Ville Syrjälä
@ 2015-10-21 12:16       ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 12:16 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 03:09:55PM +0300, Ville Syrjälä wrote:
> On Wed, Oct 21, 2015 at 12:15:42PM +0200, Daniel Vetter wrote:
> > On Wed, Oct 14, 2015 at 07:28:55PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Pull the tile width calculations from intel_fb_stride_alignment() into a
> > > new function intel_tile_width().
> > > 
> > > Also take the opportunity to pass aroun dev_priv instead of dev to
> > > intel_fb_stride_alignment().
> > > 
> > > v2: Reorder argumnents to be more consistent with other functions
> > >     Change intel_fb_stride_alignment() to accept dev_priv instead of dev
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_display.c | 76 +++++++++++++++++++++++-------------
> > >  drivers/gpu/drm/i915/intel_drv.h     |  4 +-
> > >  drivers/gpu/drm/i915/intel_sprite.c  |  2 +-
> > >  3 files changed, 51 insertions(+), 31 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index 6add8d1..c31fe47 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -2214,6 +2214,41 @@ static bool need_vtd_wa(struct drm_device *dev)
> > >  	return false;
> > >  }
> > >  
> > > +static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
> > > +				     uint64_t fb_modifier, unsigned int cpp)
> > > +{
> > > +	switch (fb_modifier) {
> > > +	case DRM_FORMAT_MOD_NONE:
> > > +		return cpp;
> > > +	case I915_FORMAT_MOD_X_TILED:
> > > +		return IS_GEN2(dev_priv) ? 128 : 512;
> > > +	case I915_FORMAT_MOD_Y_TILED:
> > > +		/* No need to check for old gens and Y tiling since this is
> > > +		 * about the display engine and those will be blocked before
> > > +		 * we get here.
> > > +		 */
> > > +		return 128;
> > 
> > Imo just drop the comment and change this to
> > 
> > 		return HAS_128_BYTE_Y_TILING(dev) 128 : 512;
> > 
> > Just to avoid wtf moments. It's less code than the comment too.
> 
> Yeah, can do. And we definitely need it if we want to use this for gem
> stuff. Although we need to change HAS_128_BYTE_Y_TILING() to include
> gen2. Currently that define actually means "has 128x32 Y tiling". Or
> we make intel_tile_width() check for 'IS_GEN2 || HAS_128_BYTE_Y_TILING'.

Oops, yeah.

> > Another one: Enforcing pot alignment for gen2/3 is fairly hapzardous - we
> > do it accidentally by requiring that for X-tiled the underlying obj is
> > also X-tiled and that strides match. Comment for this would be good here.
> > 
> > > +	case I915_FORMAT_MOD_Yf_TILED:
> > > +		switch (cpp) {
> > > +		case 1:
> > > +			return 64;
> > > +		case 2:
> > > +		case 4:
> > > +			return 128;
> > 
> > With 4 cpp we have 4x4 pixels for the 64b cacheline. So 8x8 for the 256b
> > block with 1:1 aspect ratio, hence 64x64 pixel tile for the full page.
> 
> 32x32 for the full page
> 
> > 
> > > +		case 8:
> > 
> > With 8 cpp we have 2x4 pixels for the 64b cacheline. So 8x4 for the 256b
> > block with 2:1 aspect ratio, hence 64x32 pixel tile for the full page.
> 
> 32x16 for the full page
> 
> > 
> > > +		case 16:
> > > +			return 256;
> > 
> > With 16 cpp we have 1x4 pixels for the 64b cacheline. So 4x4 for the 256b
> > block with 1:1 aspect ratio, hence 32x32 pixel tile for the full page.
> 
> 16x16 for the full page

Yeah I can't compute. But the real trouble was that I thought this was in
pixels, but it's in bytes ;-) I clarified that later on and r-b with these
numbers here.
-Daniel

> 
> > 
> > Otherwise looks good to me, Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > once we close the above.
> > 
> > Cheers, Daniel
> > 
> > > +		default:
> > > +			MISSING_CASE(cpp);
> > > +			return cpp;
> > > +		}
> > > +		break;
> > > +	default:
> > > +		MISSING_CASE(fb_modifier);
> > > +		return cpp;
> > > +	}
> > > +}
> > > +
> > >  unsigned int
> > >  intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
> > >  		  uint64_t fb_format_modifier, unsigned int plane)
> > > @@ -2895,37 +2930,20 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> > >  	POSTING_READ(reg);
> > >  }
> > >  
> > > -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
> > > -			      uint32_t pixel_format)
> > > +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> > > +			      uint64_t fb_modifier, uint32_t pixel_format)
> > >  {
> > > -	u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
> > > -
> > >  	/*
> > >  	 * The stride is either expressed as a multiple of 64 bytes
> > >  	 * chunks for linear buffers or in number of tiles for tiled
> > >  	 * buffers.
> > >  	 */
> > > -	switch (fb_modifier) {
> > > -	case DRM_FORMAT_MOD_NONE:
> > > -		return 64;
> > > -	case I915_FORMAT_MOD_X_TILED:
> > > -		if (INTEL_INFO(dev)->gen == 2)
> > > -			return 128;
> > > -		return 512;
> > > -	case I915_FORMAT_MOD_Y_TILED:
> > > -		/* No need to check for old gens and Y tiling since this is
> > > -		 * about the display engine and those will be blocked before
> > > -		 * we get here.
> > > -		 */
> > > -		return 128;
> > > -	case I915_FORMAT_MOD_Yf_TILED:
> > > -		if (bits_per_pixel == 8)
> > > -			return 64;
> > > -		else
> > > -			return 128;
> > > -	default:
> > > -		MISSING_CASE(fb_modifier);
> > > +	if (fb_modifier == DRM_FORMAT_MOD_NONE) {
> > >  		return 64;
> > > +	} else {
> > > +		unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
> > > +
> > > +		return intel_tile_width(dev_priv, fb_modifier, cpp);
> > >  	}
> > >  }
> > >  
> > > @@ -3106,7 +3124,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
> > >  	plane_ctl |= skl_plane_ctl_rotation(rotation);
> > >  
> > >  	obj = intel_fb_obj(fb);
> > > -	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> > > +	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > >  					       fb->pixel_format);
> > >  	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
> > >  
> > > @@ -9066,7 +9084,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
> > >  	fb->width = ((val >> 0) & 0x1fff) + 1;
> > >  
> > >  	val = I915_READ(PLANE_STRIDE(pipe, 0));
> > > -	stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
> > > +	stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > >  						fb->pixel_format);
> > >  	fb->pitches[0] = (val & 0x3ff) * stride_mult;
> > >  
> > > @@ -11137,7 +11155,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
> > >  	 * linear buffers or in number of tiles for tiled buffers.
> > >  	 */
> > >  	stride = fb->pitches[0] /
> > > -		 intel_fb_stride_alignment(dev, fb->modifier[0],
> > > +		 intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > >  					   fb->pixel_format);
> > >  
> > >  	/*
> > > @@ -14214,6 +14232,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
> > >  				  struct drm_mode_fb_cmd2 *mode_cmd,
> > >  				  struct drm_i915_gem_object *obj)
> > >  {
> > > +	struct drm_i915_private *dev_priv = to_i915(dev);
> > >  	unsigned int aligned_height;
> > >  	int ret;
> > >  	u32 pitch_limit, stride_alignment;
> > > @@ -14255,7 +14274,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
> > >  		return -EINVAL;
> > >  	}
> > >  
> > > -	stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
> > > +	stride_alignment = intel_fb_stride_alignment(dev_priv,
> > > +						     mode_cmd->modifier[0],
> > >  						     mode_cmd->pixel_format);
> > >  	if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
> > >  		DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index 1152566..98a8d31 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -1017,8 +1017,8 @@ unsigned int intel_fb_align_height(struct drm_device *dev,
> > >  				   uint64_t fb_format_modifier);
> > >  void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire,
> > >  			enum fb_op_origin origin);
> > > -u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
> > > -			      uint32_t pixel_format);
> > > +u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> > > +			      uint64_t fb_modifier, uint32_t pixel_format);
> > >  
> > >  /* intel_audio.c */
> > >  void intel_init_audio(struct drm_device *dev);
> > > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> > > index 90e27c8..3d96871 100644
> > > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > > @@ -215,7 +215,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> > >  				       pixel_size, true,
> > >  				       src_w != crtc_w || src_h != crtc_h);
> > >  
> > > -	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> > > +	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > >  					       fb->pixel_format);
> > >  
> > >  	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
> > > -- 
> > > 2.4.9
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 
> > -- 
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch
> 
> -- 
> Ville Syrjälä
> Intel OTC

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-21 11:28   ` Daniel Vetter
@ 2015-10-21 12:17     ` Tvrtko Ursulin
  2015-10-21 13:09       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Tvrtko Ursulin @ 2015-10-21 12:17 UTC (permalink / raw)
  To: Daniel Vetter, ville.syrjala; +Cc: intel-gfx


On 21/10/15 12:28, Daniel Vetter wrote:
> On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>
>> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
>> rotation (to find the right GTT view for it), so no need to pass all
>> kinds of plane stuff.
>>
>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Feels indeed a bit like a bikeshed and just churn without resolving the
> "pass vma in plane_state around" idea for real. But meh, it's imo not
> worse than the existing code, and looks correct. Less churn would make me
> a happier reviewer thought (there's a pile of whitespace in here too).
>
> Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

It is worse, and is definitely not better. :( Parameter reduction can be 
still accomplished without exposing one random piece of plane state in 
the function signature.

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal
  2015-10-15 12:24         ` Daniel Vetter
@ 2015-10-21 13:06           ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 13:06 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Thu, Oct 15, 2015 at 02:24:51PM +0200, Daniel Vetter wrote:
> On Thu, Oct 15, 2015 at 03:06:11PM +0300, Ville Syrjälä wrote:
> > On Thu, Oct 15, 2015 at 02:02:24PM +0200, Daniel Vetter wrote:
> > > On Thu, Oct 15, 2015 at 12:18:41PM +0100, Tvrtko Ursulin wrote:
> > > > 
> > > > On 14/10/15 17:29, ville.syrjala@linux.intel.com wrote:
> > > > >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > >
> > > > >In case we have multiple different rotated views into the same object,
> > > > >each one may need its own vma due to being of different sizes. So don't
> > > > >treat all rotated views as equal.
> > > > >
> > > > >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > >---
> > > > >  drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++
> > > > >  1 file changed, 2 insertions(+)
> > > > >
> > > > >diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > > > >index caa182f..68de734 100644
> > > > >--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> > > > >+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > > > >@@ -553,6 +553,8 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
> > > > >
> > > > >  	if (a->type != b->type)
> > > > >  		return false;
> > > > >+	if (a->type == I915_GGTT_VIEW_ROTATED)
> > > > >+		return !memcmp(&a->rotated, &b->rotated, sizeof(a->rotated));
> > > > >  	if (a->type == I915_GGTT_VIEW_PARTIAL)
> > > > >  		return !memcmp(&a->partial, &b->partial, sizeof(a->partial));
> > > > >  	return true;
> > > > 
> > > > This is where anonymous union causes problems since you have to build a
> > > > switch statement before memcmp while the original goal was for memcmp to
> > > > elegantly avoid that.
> > > 
> > > Yup, mentioned the same on irc. I much prefer we do the memcmp on type !=
> > > NORMAL, to avoid mistakes when adding more views in the future.
> > 
> > I just dislike the .partial. extra stuff all over. But whatever, it's a
> > minor detail in my book. We can go with the non-anon union if people
> > prefer that.
> 
> Here it would be
> 	if (a->type != NORMA))
> 		return !memcmp(&a->params, &b->params);
> 
> Seems at least in this case cleaner. But yet everywhere else you'll get a
> params., but that can be alleviated a bit with local variables.

We can go with your patches that preserve the named union. I can then
rebase my stuff on top.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-21 12:17     ` Tvrtko Ursulin
@ 2015-10-21 13:09       ` Ville Syrjälä
  2015-10-21 13:22         ` Tvrtko Ursulin
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 13:09 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 01:17:10PM +0100, Tvrtko Ursulin wrote:
> 
> On 21/10/15 12:28, Daniel Vetter wrote:
> > On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> >> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>
> >> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> >> rotation (to find the right GTT view for it), so no need to pass all
> >> kinds of plane stuff.
> >>
> >> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Feels indeed a bit like a bikeshed and just churn without resolving the
> > "pass vma in plane_state around" idea for real. But meh, it's imo not
> > worse than the existing code, and looks correct. Less churn would make me
> > a happier reviewer thought (there's a pile of whitespace in here too).
> >
> > Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> It is worse, and is definitely not better. :(

I might accept that if it wasn't for the ugly 'if (!plane_state)' mess.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-21 13:09       ` Ville Syrjälä
@ 2015-10-21 13:22         ` Tvrtko Ursulin
  2015-10-21 14:22           ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Tvrtko Ursulin @ 2015-10-21 13:22 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx


On 21/10/15 14:09, Ville Syrjälä wrote:
> On Wed, Oct 21, 2015 at 01:17:10PM +0100, Tvrtko Ursulin wrote:
>>
>> On 21/10/15 12:28, Daniel Vetter wrote:
>>> On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>
>>>> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
>>>> rotation (to find the right GTT view for it), so no need to pass all
>>>> kinds of plane stuff.
>>>>
>>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> Feels indeed a bit like a bikeshed and just churn without resolving the
>>> "pass vma in plane_state around" idea for real. But meh, it's imo not
>>> worse than the existing code, and looks correct. Less churn would make me
>>> a happier reviewer thought (there's a pile of whitespace in here too).
>>>
>>> Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>>
>> It is worse, and is definitely not better. :(
>
> I might accept that if it wasn't for the ugly 'if (!plane_state)' mess.

Ok you have a point there. Maybe there should be a fake default state 
available, if somehow possible? Would all zero be a valid state?

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 21/22] drm/i915: Rewrite fb rotation GTT handling
  2015-10-21 12:01     ` Daniel Vetter
@ 2015-10-21 14:19       ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 14:19 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 02:01:01PM +0200, Daniel Vetter wrote:
> On Thu, Oct 15, 2015 at 08:59:45PM +0300, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Redo the fb rotation handling in order to:
> > - eliminate the NV12 special casing
> > - handle fb->offsets[] properly
> > - make the rotation handling reasier for the plane code
> 
> I think this is too big and should be split a bit. There's also a pile of
> renames mixed int on top.

It grew from a bunch of sepearate changes, but they got gobbled
together due to changing the entire approach a few times. In the end I
was too scared to split it up anymore. But I guess I should really try.

> 
> > To achieve these goals we reduce intel_rotation_info to only contain
> > (for each plane) the rotated view width,height,stride in tile units,
> > and the page offset into the object where the plane starts. Each plane
> > is handled exactly the same way, no special casing for NV12 or other
> > formats.
> 
> That sounds like a good prep patch to split out.
> 
> > We then store the computed rotation_info under
> > intel_framebuffer so that we don't have to recompute it again.
> 
> And another one, plus then following up with the fallout.
> 
> This patch also fixes the intel_plane_obj_offset issue for earlier in the
> series. Looks good otherwise from reading through it.
> 
> > To handle fb->offsets[] we treat them as a linear offsets and convert
> > them to x/y offsets from the start of the relevant GTT mapping (either
> > normal or rotated). We store the x/y offsets under intel_framebuffer,
> > and for some extra convenience we also store the rotated pitch (ie.
> > tile aligned plane height). So for each plane we have the normal
> > x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
> > pitch is available already in fb->pitches[].
> > 
> > While we're gathering up all that extra information, we can also easily
> > compute the storage requirements for the framebuffer, so that we can
> > check that the object is big enough to hold it.
> > 
> > When it comes time to deal with the plane source coordinates, we first
> > rotate the clipped src coordinates to match the relevant GTT view
> > orientation, then add to them the fb x/y offsets. Next we compute
> > the aligned surface page offset, and as a result we're left with some
> > residual x/y offsets. Finally, if required by the hardware, we convert
> > the remaining x/y offsets into a linear offset.
> > 
> > For gen2/3 we simply skip computing the final page offset, and just
> > convert the src+fb x/y offsets directly into a linear offset since
> > that's what the hardware wants.
> > 
> > After this all platforms, incluing SKL+, compute these things in exactly
> > the same way (excluding alignemnt differences).
> > 
> > v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
> >     plane src coordinates
> >     Drop some spurious changes that got left behind during development
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Two comments below inline.
> -Daniel
> 
> > ---
> >  drivers/gpu/drm/i915/i915_gem_gtt.c  |  66 ++----
> >  drivers/gpu/drm/i915/i915_gem_gtt.h  |  14 +-
> >  drivers/gpu/drm/i915/intel_display.c | 448 ++++++++++++++++++++++++-----------
> >  drivers/gpu/drm/i915/intel_drv.h     |  32 ++-
> >  drivers/gpu/drm/i915/intel_sprite.c  | 102 ++++----
> >  5 files changed, 402 insertions(+), 260 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > index bb95b86..98aee6c 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > @@ -3255,11 +3255,6 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
> >  	unsigned int column, row;
> >  	unsigned int src_idx;
> >  
> > -	if (!sg) {
> > -		st->nents = 0;
> > -		sg = st->sgl;
> > -	}
> > -
> >  	for (column = 0; column < width; column++) {
> >  		src_idx = stride * (height - 1) + column;
> >  		for (row = 0; row < height; row++) {
> > @@ -3280,16 +3275,14 @@ rotate_pages(const dma_addr_t *in, unsigned int offset,
> >  }
> >  
> >  static struct sg_table *
> > -intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
> > +intel_rotate_fb_obj_pages(const struct intel_rotation_info *info,
> >  			  struct drm_i915_gem_object *obj)
> >  {
> > -	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
> > -	unsigned int size_pages_uv;
> > +	unsigned int size = intel_rotation_info_size(info);
> >  	struct sg_page_iter sg_iter;
> >  	unsigned long i;
> >  	dma_addr_t *page_addr_list;
> >  	struct sg_table *st;
> > -	unsigned int uv_start_page;
> >  	struct scatterlist *sg;
> >  	int ret = -ENOMEM;
> >  
> > @@ -3299,57 +3292,32 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
> >  	if (!page_addr_list)
> >  		return ERR_PTR(ret);
> >  
> > -	/* Account for UV plane with NV12. */
> > -	if (rot_info->pixel_format == DRM_FORMAT_NV12)
> > -		size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
> > -	else
> > -		size_pages_uv = 0;
> > -
> >  	/* Allocate target SG list. */
> >  	st = kmalloc(sizeof(*st), GFP_KERNEL);
> >  	if (!st)
> >  		goto err_st_alloc;
> >  
> > -	ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
> > +	ret = sg_alloc_table(st, size, GFP_KERNEL);
> >  	if (ret)
> >  		goto err_sg_alloc;
> >  
> >  	/* Populate source page list from the object. */
> >  	i = 0;
> >  	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
> > -		page_addr_list[i] = sg_page_iter_dma_address(&sg_iter);
> > -		i++;
> > +		page_addr_list[i++] = sg_page_iter_dma_address(&sg_iter);
> >  	}
> >  
> > -	/* Rotate the pages. */
> > -	sg = rotate_pages(page_addr_list, 0,
> > -		     rot_info->width_pages, rot_info->height_pages,
> > -		     rot_info->width_pages,
> > -		     st, NULL);
> > +	st->nents = 0;
> > +	sg = st->sgl;
> >  
> > -	/* Append the UV plane if NV12. */
> > -	if (rot_info->pixel_format == DRM_FORMAT_NV12) {
> > -		uv_start_page = size_pages;
> > -
> > -		/* Check for tile-row un-alignment. */
> > -		if (offset_in_page(rot_info->uv_offset))
> > -			uv_start_page--;
> > -
> > -		rot_info->uv_start_page = uv_start_page;
> > -
> > -		rotate_pages(page_addr_list, uv_start_page,
> > -			     rot_info->width_pages_uv,
> > -			     rot_info->height_pages_uv,
> > -			     rot_info->width_pages_uv,
> > -			     st, sg);
> > +	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++) {
> > +		sg = rotate_pages(page_addr_list, info->plane[i].offset,
> > +				  info->plane[i].width, info->plane[i].height,
> > +				  info->plane[i].stride, st, sg);
> >  	}
> >  
> > -	DRM_DEBUG_KMS(
> > -		      "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
> > -		      obj->base.size, rot_info->pitch, rot_info->height,
> > -		      rot_info->pixel_format, rot_info->width_pages,
> > -		      rot_info->height_pages, size_pages + size_pages_uv,
> > -		      size_pages);
> > +	DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages)\n",
> > +		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
> >  
> >  	drm_free_large(page_addr_list);
> >  
> > @@ -3360,12 +3328,8 @@ err_sg_alloc:
> >  err_st_alloc:
> >  	drm_free_large(page_addr_list);
> >  
> > -	DRM_DEBUG_KMS(
> > -		      "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
> > -		      obj->base.size, ret, rot_info->pitch, rot_info->height,
> > -		      rot_info->pixel_format, rot_info->width_pages,
> > -		      rot_info->height_pages, size_pages + size_pages_uv,
> > -		      size_pages);
> > +	DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
> > +		      obj->base.size, info->plane[0].width, info->plane[0].height, size);
> >  	return ERR_PTR(ret);
> >  }
> >  
> > @@ -3516,7 +3480,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
> >  	if (view->type == I915_GGTT_VIEW_NORMAL) {
> >  		return obj->base.size;
> >  	} else if (view->type == I915_GGTT_VIEW_ROTATED) {
> > -		return view->rotated.size;
> > +		return intel_rotation_info_size(&view->rotated) << PAGE_SHIFT;
> >  	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
> >  		return view->partial.size << PAGE_SHIFT;
> >  	} else {
> > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > index 68de734..ea28f7d 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > @@ -136,16 +136,10 @@ enum i915_ggtt_view_type {
> >  };
> >  
> >  struct intel_rotation_info {
> > -	unsigned int height;
> > -	unsigned int pitch;
> > -	unsigned int uv_offset;
> > -	uint32_t pixel_format;
> > -	uint64_t fb_modifier;
> > -	unsigned int width_pages, height_pages;
> > -	uint64_t size;
> > -	unsigned int width_pages_uv, height_pages_uv;
> > -	uint64_t size_uv;
> > -	unsigned int uv_start_page;
> > +	struct {
> > +		/* tiles */
> > +		unsigned int width, height, stride, offset;
> > +	} plane[2];
> >  };
> >  
> >  struct i915_ggtt_view {
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 028dc4a..0dcb710 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2274,49 +2274,28 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
> >  	return ALIGN(height, tile_height);
> >  }
> >  
> > -static int
> > +unsigned int intel_rotation_info_size(const struct intel_rotation_info *info)
> > +{
> > +	unsigned int size = 0;
> > +	int i;
> > +
> > +	for (i = 0 ; i < ARRAY_SIZE(info->plane); i++)
> > +		size += info->plane[i].width * info->plane[i].height;
> > +
> > +	return size;
> > +}
> > +
> > +static void
> >  intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> >  			const struct drm_framebuffer *fb,
> >  			unsigned int rotation)
> >  {
> > -	struct drm_i915_private *dev_priv = to_i915(fb->dev);
> > -	struct intel_rotation_info *info = &view->rotated;
> > -	unsigned int tile_size, tile_width, tile_height, cpp;
> > -
> > -	*view = i915_ggtt_view_normal;
> > -
> > -	if (!intel_rotation_90_or_270(rotation))
> > -		return 0;
> > -
> > -	*view = i915_ggtt_view_rotated;
> > -
> > -	info->height = fb->height;
> > -	info->pixel_format = fb->pixel_format;
> > -	info->pitch = fb->pitches[0];
> > -	info->uv_offset = fb->offsets[1];
> > -	info->fb_modifier = fb->modifier[0];
> > -
> > -	tile_size = intel_tile_size(dev_priv);
> > -
> > -	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > -	tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
> > -	tile_height = tile_size / tile_width;
> > -
> > -	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
> > -	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
> > -	info->size = info->width_pages * info->height_pages * tile_size;
> > -
> > -	if (info->pixel_format == DRM_FORMAT_NV12) {
> > -		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
> > -		tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
> > -		tile_height = tile_size / tile_width;
> > -
> > -		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
> > -		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
> > -		info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
> > +	if (intel_rotation_90_or_270(rotation)) {
> > +		*view = i915_ggtt_view_rotated;
> > +		view->rotated = to_intel_framebuffer(fb)->info;
> > +	} else {
> > +		*view = i915_ggtt_view_normal;
> >  	}
> > -
> > -	return 0;
> >  }
> >  
> >  static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
> > @@ -2368,9 +2347,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
> >  
> >  	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
> >  
> > -	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
> > -	if (ret)
> > -		return ret;
> > +	intel_fill_fb_ggtt_view(&view, fb, rotation);
> >  
> >  	/* Note that the w/a also requires 64 PTE of padding following the
> >  	 * bo. We currently fill all unused PTE with the shadow page and so
> > @@ -2433,18 +2410,31 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation
> >  {
> >  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >  	struct i915_ggtt_view view;
> > -	int ret;
> >  
> >  	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
> >  
> > -	ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
> > -	WARN_ONCE(ret, "Couldn't get view from plane state!");
> > +	intel_fill_fb_ggtt_view(&view, fb, rotation);
> >  
> >  	i915_gem_object_unpin_fence(obj);
> >  	i915_gem_object_unpin_from_display_plane(obj, &view);
> >  }
> >  
> >  /*
> > + * Convert the x/y offsets into a linear offset.
> > + * Only valid with 0/180 degree rotation, which is fine since linear
> > + * offset is only used with linear buffers on pre-hsw and tiled buffers
> > + * with gen2/3, and 90/270 degree rotations isn't supported on any of them.
> > + */
> > +unsigned int intel_fb_xy_to_linear(int x, int y,
> > +				   const struct drm_framebuffer *fb, int plane)
> > +{
> > +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > +	unsigned int pitch = fb->pitches[plane];
> > +
> > +	return y * pitch + x * cpp;
> > +}
> > +
> > +/*
> >   * Return the tile dimensions in pixel units matching
> >   * the specified rotation angle.
> >   */
> > @@ -2475,6 +2465,55 @@ static void intel_rotate_tile_dims(unsigned int *tile_width,
> >  }
> >  
> >  /*
> > + * Add the x/y offsets derived from fb->offsets[] to the user
> > + * specified plane src x/y offsets. The resulting x/y offsets
> > + * specify the start of scanout from the beginning of the gtt mapping.
> > + */
> > +void intel_add_fb_offsets(int *x, int *y,
> > +			  const struct drm_framebuffer *fb, int plane,
> > +			  unsigned int rotation)
> > +
> > +{
> > +	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> > +	const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > +	unsigned int pitch;
> > +
> > +	if (intel_rotation_90_or_270(rotation)) {
> > +		pitch = intel_fb->plane[plane].rotated.pitch;
> > +
> > +		*x += intel_fb->plane[plane].rotated.x;
> > +		*y += intel_fb->plane[plane].rotated.y;
> > +	} else {
> > +		pitch = fb->pitches[plane];
> > +
> > +		*x += intel_fb->plane[plane].normal.x;
> > +		*y += intel_fb->plane[plane].normal.y;
> > +	}
> > +
> > +	/* minimize x */
> > +	if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
> > +		unsigned int tile_size, tile_width, tile_height;
> > +
> > +		tile_size = intel_tile_size(dev_priv);
> > +		tile_width = intel_tile_width(dev_priv, fb->modifier[plane], cpp);
> > +		tile_height = tile_size / tile_width;
> > +
> > +		intel_rotate_tile_dims(&tile_width, &tile_height,
> > +				       &pitch, cpp, rotation);
> > +
> > +		*y += *x / pitch * tile_height;
> > +		*x  = *x % pitch;
> > +	} else {
> > +		/* in pixels */
> > +		pitch /= cpp;
> > +
> > +		*y += *x / pitch;
> > +		*x  = *x % pitch;
> > +	}
> 
> This is called before we do the entire page_offset dance, so I don't think
> we need a special case for tiled vs. untiled.

Hmm. I think this is leftover from some earlier version where I did
stuff in a different order. Yeah, the page_offset stuff should deal
with this just fine, and for gen2/3 we just convert it to a linear 
offset anyway so it's the same thing in the end. I'll just throw the
entire "minimize x" crap in the bin.

> -Daniel
> 
> > +}
> > +
> > +/*
> >   * Adjust the page offset by moving the difference into
> >   * the x/y offsets.
> >   *
> > @@ -2514,20 +2553,23 @@ static void intel_adjust_page_offset(int *x, int *y,
> >   * In the 90/270 rotated case, x and y are assumed
> >   * to be already rotated to match the rotated GTT view, and
> >   * pitch is the tile_height aligned framebuffer height.
> > + *
> > + * This function is used when computing the derived information
> > + * under intel_framebuffer, so using any of that information
> > + * here is not allowed. Anything under drm_framebuffer can be
> > + * used. This is why the user has to pass in the pitch since it
> > + * is specified in the rotated orientation.
> >   */
> > -unsigned long intel_compute_page_offset(int *x, int *y,
> > -					const struct drm_framebuffer *fb, int plane,
> > -					unsigned int pitch,
> > -					unsigned int rotation)
> > +static unsigned int _intel_compute_page_offset(const struct drm_i915_private *dev_priv,
> > +					       int *x, int *y,
> > +					       const struct drm_framebuffer *fb, int plane,
> > +					       unsigned int pitch,
> > +					       unsigned int rotation,
> > +					       unsigned int alignment)
> >  {
> > -	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> >  	uint64_t fb_modifier = fb->modifier[plane];
> >  	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > -	unsigned int offset, alignment;
> > -
> > -	alignment = intel_surf_alignment(dev_priv, fb_modifier);
> > -	if (alignment)
> > -		alignment--;
> > +	unsigned int offset;
> >  
> >  	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
> >  		unsigned int tile_size, tile_width, tile_height;
> > @@ -2560,6 +2602,145 @@ unsigned long intel_compute_page_offset(int *x, int *y,
> >  	return offset & ~alignment;
> >  }
> >  
> > +unsigned int intel_compute_page_offset(int *x, int *y,
> > +				       const struct drm_framebuffer *fb, int plane,
> > +				       unsigned int pitch,
> > +				       unsigned int rotation)
> > +{
> > +	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> > +	unsigned int alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
> > +
> > +	return _intel_compute_page_offset(dev_priv, x, y, fb, plane, pitch,
> > +					  rotation, alignment ? (alignment - 1) : 0);
> > +}
> > +
> > +/* Convert the fb->offset[] linear offset into x/y offsets */
> > +static void intel_fb_offset_to_xy(int *x, int *y,
> > +				  const struct drm_framebuffer *fb, int plane)
> > +{
> > +	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > +	unsigned int pitch = fb->pitches[plane];
> > +	unsigned int linear_offset = fb->offsets[plane];
> > +
> > +	*y = linear_offset / pitch;
> > +	*x = linear_offset % pitch / cpp;
> > +}
> > +
> > +static int
> > +intel_fill_fb_info(struct drm_i915_private *dev_priv,
> > +		   struct drm_framebuffer *fb)
> > +{
> > +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +	struct intel_rotation_info *info = &intel_fb->info;
> > +	unsigned int tile_size;
> > +	unsigned int gtt_offset_rotated = 0;
> > +	unsigned int max_size = 0;
> > +	uint32_t format = fb->pixel_format;
> > +	int i, num_planes = drm_format_num_planes(format);
> > +
> > +	tile_size = intel_tile_size(dev_priv);
> > +
> > +	for (i = 0; i < num_planes; i++) {
> > +		unsigned int width, height;
> > +		unsigned int cpp, offset, size;
> > +		int x, y;
> > +
> > +		cpp = drm_format_plane_cpp(format, i);
> > +		width = drm_format_plane_width(fb->width, format, i);
> > +		height = drm_format_plane_height(fb->height, format, i);
> > +
> > +		intel_fb_offset_to_xy(&x, &y, fb, i);
> > +
> > +		/*
> > +		 * First pixel of the framebuffer from
> > +		 * the start of the normal gtt mapping.
> > +		 */
> > +		intel_fb->plane[i].normal.x = x;
> > +		intel_fb->plane[i].normal.y = y;
> > +
> > +		offset = _intel_compute_page_offset(dev_priv, &x, &y,
> > +						    fb, 0, fb->pitches[i],
> > +						    BIT(DRM_ROTATE_0),
> > +						    tile_size);
> > +		offset /= tile_size;
> > +		DRM_DEBUG("page offset %u pages\n", offset);
> > +
> > +		if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
> > +			unsigned int tile_width, tile_height;
> > +			unsigned int pitch;
> > +			struct drm_rect r;
> > +
> > +			tile_width = intel_tile_width(dev_priv, fb->modifier[i], cpp);
> > +			tile_height = tile_size / tile_width;
> > +
> > +			info->plane[i].offset = offset;
> > +			info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width);
> > +			info->plane[i].width = DIV_ROUND_UP((x + width) * cpp, tile_width);
> > +			info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
> > +
> > +
> > +			intel_fb->plane[i].rotated.pitch =
> > +				info->plane[i].height * tile_height;
> > +
> > +			/* how many tiles does this plane need */
> > +			size = info->plane[i].stride * info->plane[i].height;
> > +			/*
> > +			 * If the plane isn't horizontally tile aligned,
> > +			 * we need one more tile.
> > +			 */
> > +			if (x != 0)
> > +				size++;
> > +
> > +			pitch = intel_fb->plane[i].rotated.pitch;
> > +
> > +			/* rotate the x/y offsets to match the GTT view */
> > +			r.x1 = x;
> > +			r.y1 = y;
> > +			r.x2 = x + width;
> > +			r.y2 = y + height;
> > +			drm_rect_rotate(&r, width, pitch, BIT(DRM_ROTATE_270));
> > +			x = r.x1;
> > +			y = r.y1;
> > +
> > +			intel_rotate_tile_dims(&tile_width, &tile_height, &pitch,
> > +					       cpp, BIT(DRM_ROTATE_270));
> > +
> > +			/*
> > +			 * We only keep the x/y offsets, so push all of the
> > +			 * gtt offset into the x/y offsets.
> > +			 */
> > +			intel_adjust_page_offset(&x, &y, tile_width, tile_height,
> > +						 tile_size, pitch,
> > +						 gtt_offset_rotated * tile_size, 0);
> > +
> > +			gtt_offset_rotated += info->plane[i].width * info->plane[i].height;
> > +
> > +			/*
> > +			 * First pixel of the framebuffer from
> > +			 * the start of the rotated gtt mapping.
> > +			 */
> > +			intel_fb->plane[i].rotated.x = x;
> > +			intel_fb->plane[i].rotated.y = y;
> > +		} else {
> > +			size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
> > +					    x * cpp, tile_size);
> > +		}
> > +		DRM_DEBUG("%d offset %u, size %u, stride %u, height %u\n",
> > +			  i, offset, size, info->plane[i].stride, info->plane[i].height);
> > +
> > +		/* how many tiles in total needed in the bo */
> > +		max_size = max(max_size, offset + size);
> > +	}
> > +
> > +	if (max_size * tile_size > to_intel_framebuffer(fb)->obj->base.size) {
> > +		DRM_DEBUG("fb too big for bo (need %u bytes, have %zu bytes)\n",
> > +			  max_size * tile_size, to_intel_framebuffer(fb)->obj->base.size);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  static int i9xx_format_to_fourcc(int format)
> >  {
> >  	switch (format) {
> > @@ -2761,7 +2942,7 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
> >  	struct drm_i915_gem_object *obj;
> >  	int plane = intel_crtc->plane;
> >  	unsigned int rotation;
> > -	unsigned long linear_offset;
> > +	unsigned int linear_offset;
> >  	u32 dspcntr;
> >  	u32 reg = DSPCNTR(plane);
> >  	int pixel_size;
> > @@ -2839,30 +3020,25 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
> >  	if (IS_G4X(dev))
> >  		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> >  
> > -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >  
> > -	if (INTEL_INFO(dev)->gen >= 4) {
> > +	if (INTEL_INFO(dev)->gen >= 4)
> >  		intel_crtc->dspaddr_offset =
> >  			intel_compute_page_offset(&x, &y, fb, 0,
> >  						  fb->pitches[0], rotation);
> > -		linear_offset -= intel_crtc->dspaddr_offset;
> > -	} else {
> > -		intel_crtc->dspaddr_offset = linear_offset;
> > -	}
> >  
> >  	if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
> >  		dspcntr |= DISPPLANE_ROTATE_180;
> >  
> >  		x += (intel_crtc->config->pipe_src_w - 1);
> >  		y += (intel_crtc->config->pipe_src_h - 1);
> > -
> > -		/* Finding the last pixel of the last line of the display
> > -		data and adding to linear_offset*/
> > -		linear_offset +=
> > -			(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
> > -			(intel_crtc->config->pipe_src_w - 1) * pixel_size;
> >  	}
> >  
> > +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> > +	if (INTEL_INFO(dev)->gen < 4)
> > +		intel_crtc->dspaddr_offset = linear_offset;
> > +
> >  	intel_crtc->adjusted_x = x;
> >  	intel_crtc->adjusted_y = y;
> >  
> > @@ -2871,7 +3047,8 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
> >  	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
> >  	if (INTEL_INFO(dev)->gen >= 4) {
> >  		I915_WRITE(DSPSURF(plane),
> > -			   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
> > +			   intel_surf_gtt_offset(fb, 0, rotation) +
> > +			   intel_crtc->dspaddr_offset);
> >  		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
> >  		I915_WRITE(DSPLINOFF(plane), linear_offset);
> >  	} else
> > @@ -2891,7 +3068,7 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> >  	struct drm_i915_gem_object *obj;
> >  	int plane = intel_crtc->plane;
> >  	unsigned int rotation;
> > -	unsigned long linear_offset;
> > +	unsigned int linear_offset;
> >  	u32 dspcntr;
> >  	u32 reg = DSPCNTR(plane);
> >  	int pixel_size;
> > @@ -2946,26 +3123,22 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> >  	if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
> >  		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> >  
> > -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >  	intel_crtc->dspaddr_offset =
> >  		intel_compute_page_offset(&x, &y, fb, 0,
> >  					  fb->pitches[0], rotation);
> > -	linear_offset -= intel_crtc->dspaddr_offset;
> > +
> >  	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		dspcntr |= DISPPLANE_ROTATE_180;
> >  
> >  		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> >  			x += (intel_crtc->config->pipe_src_w - 1);
> >  			y += (intel_crtc->config->pipe_src_h - 1);
> > -
> > -			/* Finding the last pixel of the last line of the display
> > -			data and adding to linear_offset*/
> > -			linear_offset +=
> > -				(intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
> > -				(intel_crtc->config->pipe_src_w - 1) * pixel_size;
> >  		}
> >  	}
> >  
> > +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >  	intel_crtc->adjusted_x = x;
> >  	intel_crtc->adjusted_y = y;
> >  
> > @@ -2973,7 +3146,8 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
> >  
> >  	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
> >  	I915_WRITE(DSPSURF(plane),
> > -		   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
> > +		   intel_surf_gtt_offset(fb, 0, rotation) +
> > +		   intel_crtc->dspaddr_offset);
> >  	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> >  		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
> >  	} else {
> > @@ -3000,30 +3174,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> >  	}
> >  }
> >  
> > -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
> > -				     struct drm_i915_gem_object *obj,
> > -				     unsigned int plane)
> > +unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
> > +				   unsigned int rotation)
> 
> If you want to frob the interface, then I'd replace the fb and rotation
> with the plane state.

Hmm. Yeah here we should always have a plane state, so could pass that
in. It's a bit funky passing in the plane state and the (color) plane
index. Usually the latter goes with fb or pixel format. But I think I
already have some wm cleanup stuff somewhere that does the same actually,
so might as well do it here.

I'm also thinking we may want to move a bunch of this coordinate
mangling into the check phase of the operation and reduce the commit
to just getting the vma offset and adding it with the page_offset
computed in check(). But I'll leave that for the future.

> 
> >  {
> > -	const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
> > -	struct i915_vma *vma;
> > -	unsigned char *offset;
> > +	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +	struct i915_ggtt_view view;
> >  
> > -	if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
> > -		view = &i915_ggtt_view_rotated;
> > +	intel_fill_fb_ggtt_view(&view, fb, rotation);
> >  
> > -	vma = i915_gem_obj_to_ggtt_view(obj, view);
> > -	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
> > -		view->type))
> > -		return -1;
> > -
> > -	offset = (unsigned char *)vma->node.start;
> > -
> > -	if (plane == 1) {
> > -		offset += vma->ggtt_view.rotated.uv_start_page *
> > -			  PAGE_SIZE;
> > -	}
> > -
> > -	return (unsigned long)offset;
> > +	return i915_gem_obj_ggtt_offset_view(obj, &view);
> >  }
> >  
> >  static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
> > @@ -3142,18 +3301,16 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >  	struct drm_plane *plane = crtc->primary;
> > +	struct intel_framebuffer *intel_fb;
> >  	bool visible = to_intel_plane_state(plane->state)->visible;
> > -	struct drm_i915_gem_object *obj;
> >  	int pipe = intel_crtc->pipe;
> >  	u32 plane_ctl, stride_div, stride;
> > -	u32 tile_height, plane_offset, plane_size;
> >  	unsigned int rotation;
> > -	int x_offset, y_offset;
> >  	unsigned long surf_addr;
> >  	struct intel_crtc_state *crtc_state = intel_crtc->config;
> >  	struct intel_plane_state *plane_state;
> > -	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
> > -	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
> > +	int src_w, src_h;
> > +	int dst_x, dst_y, dst_w, dst_h;
> >  	int scaler_id = -1;
> >  	int pixel_size;
> >  
> > @@ -3166,6 +3323,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
> >  		return;
> >  	}
> >  
> > +	intel_fb = to_intel_framebuffer(fb);
> >  	pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  
> >  	plane_ctl = PLANE_CTL_ENABLE |
> > @@ -3179,16 +3337,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
> >  	rotation = plane->state->rotation;
> >  	plane_ctl |= skl_plane_ctl_rotation(rotation);
> >  
> > -	obj = intel_fb_obj(fb);
> > -	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > -					       fb->pixel_format);
> > -	surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
> > -
> > -	WARN_ON(drm_rect_width(&plane_state->src) == 0);
> > -
> >  	scaler_id = plane_state->scaler_id;
> > -	src_x = plane_state->src.x1 >> 16;
> > -	src_y = plane_state->src.y1 >> 16;
> >  	src_w = drm_rect_width(&plane_state->src) >> 16;
> >  	src_h = drm_rect_height(&plane_state->src) >> 16;
> >  	dst_x = plane_state->dst.x1;
> > @@ -3196,31 +3345,48 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
> >  	dst_w = drm_rect_width(&plane_state->dst);
> >  	dst_h = drm_rect_height(&plane_state->dst);
> >  
> > -	WARN_ON(x != src_x || y != src_y);
> > -
> >  	if (intel_rotation_90_or_270(rotation)) {
> > -		/* stride = Surface height in tiles */
> > -		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> > -						pixel_size);
> > -		stride = DIV_ROUND_UP(fb->height, tile_height);
> > -		x_offset = stride * tile_height - y - src_h;
> > -		y_offset = x;
> > -		plane_size = (src_w - 1) << 16 | (src_h - 1);
> > +		struct drm_rect r = {
> > +			.x1 = x,
> > +			.x2 = x + src_w,
> > +			.y1 = y,
> > +			.y2 = y + src_h,
> > +		};
> > +
> > +		/* Rotate src coordinates to match rotated GTT view */
> > +		drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
> > +
> > +		x = r.x1;
> > +		y = r.y1;
> > +		src_w = drm_rect_width(&r);
> > +		src_h = drm_rect_height(&r);
> > +
> > +		stride_div = intel_tile_height(dev_priv, fb->modifier[0],
> > +					       pixel_size);
> > +		stride = intel_fb->plane[0].rotated.pitch;
> >  	} else {
> > -		stride = fb->pitches[0] / stride_div;
> > -		x_offset = x;
> > -		y_offset = y;
> > -		plane_size = (src_h - 1) << 16 | (src_w - 1);
> > +		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > +						       fb->pixel_format);
> > +		stride = fb->pitches[0];
> >  	}
> > -	plane_offset = y_offset << 16 | x_offset;
> >  
> > -	intel_crtc->adjusted_x = x_offset;
> > -	intel_crtc->adjusted_y = y_offset;
> > +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > +	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> > +					      stride, rotation);
> > +
> > +	/* Sizes are 0 based */
> > +	src_w--;
> > +	src_h--;
> > +	dst_w--;
> > +	dst_h--;
> > +
> > +	intel_crtc->adjusted_x = x;
> > +	intel_crtc->adjusted_y = y;
> >  
> >  	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
> > -	I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
> > -	I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
> > -	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
> > +	I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
> > +	I915_WRITE(PLANE_STRIDE(pipe, 0), stride / stride_div);
> > +	I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w);
> >  
> >  	if (scaler_id >= 0) {
> >  		uint32_t ps_ctrl = 0;
> > @@ -3237,7 +3403,8 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
> >  		I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);
> >  	}
> >  
> > -	I915_WRITE(PLANE_SURF(pipe, 0), surf_addr);
> > +	I915_WRITE(PLANE_SURF(pipe, 0),
> > +		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
> >  
> >  	POSTING_READ(PLANE_SURF(pipe, 0));
> >  }
> > @@ -11521,8 +11688,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> >  	if (ret)
> >  		goto cleanup_pending;
> >  
> > -	work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
> > -						  obj, 0);
> > +	work->gtt_offset = intel_surf_gtt_offset(fb, 0, primary->state->rotation);
> >  	work->gtt_offset += intel_crtc->dspaddr_offset;
> >  
> >  	if (mmio_flip) {
> > @@ -14319,7 +14485,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
> >  				  struct drm_i915_gem_object *obj)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> > -	unsigned int aligned_height;
> >  	int ret;
> >  	u32 pitch_limit, stride_alignment;
> >  
> > @@ -14443,16 +14608,13 @@ static int intel_framebuffer_init(struct drm_device *dev,
> >  	if (ret)
> >  		return ret;
> >  
> > -	aligned_height = intel_fb_align_height(dev, mode_cmd->height,
> > -					       mode_cmd->pixel_format,
> > -					       mode_cmd->modifier[0]);
> > -	/* FIXME drm helper for size checks (especially planar formats)? */
> > -	if (obj->base.size < aligned_height * mode_cmd->pitches[0])
> > -		return -EINVAL;
> > -
> >  	drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
> >  	intel_fb->obj = obj;
> >  
> > +	ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
> > +	if (ret)
> > +		return ret;
> > +
> >  	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
> >  	if (ret) {
> >  		DRM_ERROR("framebuffer init failed %d\n", ret);
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 36d049d..395afd3 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -118,6 +118,19 @@ enum intel_output_type {
> >  struct intel_framebuffer {
> >  	struct drm_framebuffer base;
> >  	struct drm_i915_gem_object *obj;
> > +	struct intel_rotation_info info;
> > +
> > +	struct {
> > +		struct {
> > +			/* pixels */
> > +			unsigned int x, y;
> > +		} normal;
> > +		struct {
> > +			/* pixels */
> > +			unsigned int x, y;
> > +			unsigned int pitch;
> > +		} rotated;
> > +	} plane[2];
> >  };
> >  
> >  struct intel_fbdev {
> > @@ -1028,6 +1041,12 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv);
> >  void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
> >  
> >  /* intel_display.c */
> > +unsigned int intel_rotation_info_size(const struct intel_rotation_info *info);
> > +unsigned int intel_fb_xy_to_linear(int x, int y,
> > +				   const struct drm_framebuffer *fb, int plane);
> > +void intel_add_fb_offsets(int *x, int *y,
> > +			  const struct drm_framebuffer *fb, int plane,
> > +			  unsigned int rotation);
> >  extern const struct drm_plane_funcs intel_plane_funcs;
> >  bool intel_has_pending_fb_unpin(struct drm_device *dev);
> >  int intel_pch_rawclk(struct drm_device *dev);
> > @@ -1134,10 +1153,10 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
> >  void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
> >  #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
> >  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
> > -unsigned long intel_compute_page_offset(int *x, int *y,
> > -					const struct drm_framebuffer *fb, int plane,
> > -					unsigned int pitch,
> > -					unsigned int rotation);
> > +unsigned int intel_compute_page_offset(int *x, int *y,
> > +				       const struct drm_framebuffer *fb, int plane,
> > +				       unsigned int pitch,
> > +				       unsigned int rotation);
> >  void intel_prepare_reset(struct drm_device *dev);
> >  void intel_finish_reset(struct drm_device *dev);
> >  void hsw_enable_pc8(struct drm_i915_private *dev_priv);
> > @@ -1174,9 +1193,8 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
> >  int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
> >  int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
> >  
> > -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
> > -				     struct drm_i915_gem_object *obj,
> > -				     unsigned int plane);
> > +unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
> > +				   unsigned int rotation);
> >  
> >  u32 skl_plane_ctl_format(uint32_t pixel_format);
> >  u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> > index 828c3eb..d9d37b0 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -188,17 +188,15 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> >  	struct drm_device *dev = drm_plane->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
> > -	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> >  	const int pipe = intel_plane->pipe;
> >  	const int plane = intel_plane->plane + 1;
> >  	u32 plane_ctl, stride_div, stride;
> >  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  	const struct drm_intel_sprite_colorkey *key =
> >  		&to_intel_plane_state(drm_plane->state)->ckey;
> > -	unsigned long surf_addr;
> > -	u32 tile_height, plane_offset, plane_size;
> > +	unsigned int surf_addr;
> >  	unsigned int rotation;
> > -	int x_offset, y_offset;
> >  	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
> >  	int scaler_id;
> >  
> > @@ -215,17 +213,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> >  				       pixel_size, true,
> >  				       src_w != crtc_w || src_h != crtc_h);
> >  
> > -	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > -					       fb->pixel_format);
> > -
> >  	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
> >  
> > -	/* Sizes are 0 based */
> > -	src_w--;
> > -	src_h--;
> > -	crtc_w--;
> > -	crtc_h--;
> > -
> >  	if (key->flags) {
> >  		I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
> >  		I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
> > @@ -237,27 +226,43 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> >  	else if (key->flags & I915_SET_COLORKEY_SOURCE)
> >  		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
> >  
> > -	surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
> > -
> >  	if (intel_rotation_90_or_270(rotation)) {
> > -		/* stride: Surface height in tiles */
> > -		tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> > -						pixel_size);
> > -		stride = DIV_ROUND_UP(fb->height, tile_height);
> > -		plane_size = (src_w << 16) | src_h;
> > -		x_offset = stride * tile_height - y - (src_h + 1);
> > -		y_offset = x;
> > +		struct drm_rect r = {
> > +			.x1 = x,
> > +			.x2 = x + src_w,
> > +			.y1 = y,
> > +			.y2 = y + src_h,
> > +		};
> > +
> > +		/* Rotate src coordinates to match rotated GTT view */
> > +		drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
> > +
> > +		x = r.x1;
> > +		y = r.y1;
> > +		src_w = drm_rect_width(&r);
> > +		src_h = drm_rect_height(&r);
> > +
> > +		stride_div = intel_tile_height(dev_priv, fb->modifier[0], pixel_size);
> > +		stride = intel_fb->plane[0].rotated.pitch;
> >  	} else {
> > -		stride = fb->pitches[0] / stride_div;
> > -		plane_size = (src_h << 16) | src_w;
> > -		x_offset = x;
> > -		y_offset = y;
> > +		stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > +						       fb->pixel_format);
> > +		stride = fb->pitches[0];
> >  	}
> > -	plane_offset = y_offset << 16 | x_offset;
> >  
> > -	I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
> > -	I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
> > -	I915_WRITE(PLANE_SIZE(pipe, plane), plane_size);
> > +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > +	surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> > +					      stride, rotation);
> > +
> > +	/* Sizes are 0 based */
> > +	src_w--;
> > +	src_h--;
> > +	crtc_w--;
> > +	crtc_h--;
> > +
> > +	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
> > +	I915_WRITE(PLANE_STRIDE(pipe, plane), stride / stride_div);
> > +	I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
> >  
> >  	/* program plane scaler */
> >  	if (scaler_id >= 0) {
> > @@ -279,7 +284,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> >  	}
> >  
> >  	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
> > -	I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
> > +	I915_WRITE(PLANE_SURF(pipe, plane),
> > +		   intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
> >  	POSTING_READ(PLANE_SURF(pipe, plane));
> >  }
> >  
> > @@ -355,8 +361,7 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
> >  	int plane = intel_plane->plane;
> >  	u32 sprctl;
> >  	unsigned int rotation = dplane->state->rotation;
> > -	unsigned long sprsurf_offset, linear_offset;
> > -	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> > +	unsigned int sprsurf_offset, linear_offset;
> >  	const struct drm_intel_sprite_colorkey *key =
> >  		&to_intel_plane_state(dplane->state)->ckey;
> >  
> > @@ -420,19 +425,19 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
> >  	crtc_w--;
> >  	crtc_h--;
> >  
> > -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >  	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> >  						   fb->pitches[0], rotation);
> > -	linear_offset -= sprsurf_offset;
> >  
> >  	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		sprctl |= SP_ROTATE_180;
> >  
> >  		x += src_w;
> >  		y += src_h;
> > -		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
> >  	}
> >  
> > +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >  	if (key->flags) {
> >  		I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
> >  		I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
> > @@ -457,8 +462,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
> >  
> >  	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
> >  	I915_WRITE(SPCNTR(pipe, plane), sprctl);
> > -	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
> > -		   sprsurf_offset);
> > +	I915_WRITE(SPSURF(pipe, plane),
> > +		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
> >  	POSTING_READ(SPSURF(pipe, plane));
> >  }
> >  
> > @@ -492,7 +497,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	enum pipe pipe = intel_plane->pipe;
> >  	u32 sprctl, sprscale = 0;
> >  	unsigned int rotation = plane->state->rotation;
> > -	unsigned long sprsurf_offset, linear_offset;
> > +	unsigned int sprsurf_offset, linear_offset;
> >  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  	const struct drm_intel_sprite_colorkey *key =
> >  		&to_intel_plane_state(plane->state)->ckey;
> > @@ -552,10 +557,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	if (crtc_w != src_w || crtc_h != src_h)
> >  		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
> >  
> > -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >  	sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> >  						   fb->pitches[0], rotation);
> > -	linear_offset -= sprsurf_offset;
> >  
> >  	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		sprctl |= SPRITE_ROTATE_180;
> > @@ -564,11 +568,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> >  			x += src_w;
> >  			y += src_h;
> > -			linear_offset += src_h * fb->pitches[0] +
> > -				src_w * pixel_size;
> >  		}
> >  	}
> >  
> > +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >  	if (key->flags) {
> >  		I915_WRITE(SPRKEYVAL(pipe), key->min_value);
> >  		I915_WRITE(SPRKEYMAX(pipe), key->max_value);
> > @@ -597,7 +601,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  		I915_WRITE(SPRSCALE(pipe), sprscale);
> >  	I915_WRITE(SPRCTL(pipe), sprctl);
> >  	I915_WRITE(SPRSURF(pipe),
> > -		   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
> > +		   intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
> >  	POSTING_READ(SPRSURF(pipe));
> >  }
> >  
> > @@ -632,7 +636,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >  	int pipe = intel_plane->pipe;
> >  	unsigned int rotation = plane->state->rotation;
> > -	unsigned long dvssurf_offset, linear_offset;
> > +	unsigned int dvssurf_offset, linear_offset;
> >  	u32 dvscntr, dvsscale;
> >  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  	const struct drm_intel_sprite_colorkey *key =
> > @@ -689,19 +693,19 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	if (crtc_w != src_w || crtc_h != src_h)
> >  		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
> >  
> > -	linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +	intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >  	dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> >  						   fb->pitches[0], rotation);
> > -	linear_offset -= dvssurf_offset;
> >  
> >  	if (rotation == BIT(DRM_ROTATE_180)) {
> >  		dvscntr |= DVS_ROTATE_180;
> >  
> >  		x += src_w;
> >  		y += src_h;
> > -		linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
> >  	}
> >  
> > +	linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >  	if (key->flags) {
> >  		I915_WRITE(DVSKEYVAL(pipe), key->min_value);
> >  		I915_WRITE(DVSKEYMAX(pipe), key->max_value);
> > @@ -725,7 +729,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> >  	I915_WRITE(DVSSCALE(pipe), dvsscale);
> >  	I915_WRITE(DVSCNTR(pipe), dvscntr);
> >  	I915_WRITE(DVSSURF(pipe),
> > -		   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
> > +		   intel_surf_gtt_offset(fb, 0, rotation) + dvssurf_offset);
> >  	POSTING_READ(DVSSURF(pipe));
> >  }
> >  
> > -- 
> > 2.4.9
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-21 13:22         ` Tvrtko Ursulin
@ 2015-10-21 14:22           ` Ville Syrjälä
  2015-10-21 15:20             ` Daniel Vetter
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 14:22 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 02:22:10PM +0100, Tvrtko Ursulin wrote:
> 
> On 21/10/15 14:09, Ville Syrjälä wrote:
> > On Wed, Oct 21, 2015 at 01:17:10PM +0100, Tvrtko Ursulin wrote:
> >>
> >> On 21/10/15 12:28, Daniel Vetter wrote:
> >>> On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> >>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>>
> >>>> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> >>>> rotation (to find the right GTT view for it), so no need to pass all
> >>>> kinds of plane stuff.
> >>>>
> >>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>
> >>> Feels indeed a bit like a bikeshed and just churn without resolving the
> >>> "pass vma in plane_state around" idea for real. But meh, it's imo not
> >>> worse than the existing code, and looks correct. Less churn would make me
> >>> a happier reviewer thought (there's a pile of whitespace in here too).
> >>>
> >>> Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> >>
> >> It is worse, and is definitely not better. :(
> >
> > I might accept that if it wasn't for the ugly 'if (!plane_state)' mess.
> 
> Ok you have a point there. Maybe there should be a fake default state 
> available, if somehow possible? Would all zero be a valid state?

Let's not start adding fake stuff, that's going to be even more
confusing. IMO the correct approach is to have a low level function that
doesn't depend on the state (which is what we have after my patch more or
less), and then we can just wrap it up in nicer clothing for most normal
users.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic
  2015-10-21 12:09   ` Daniel Vetter
@ 2015-10-21 15:15     ` Daniel Vetter
  0 siblings, 0 replies; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 15:15 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 02:09:00PM +0200, Daniel Vetter wrote:
> On Wed, Oct 14, 2015 at 06:59:38PM +0200, Daniel Vetter wrote:
> > On Wed, Oct 14, 2015 at 07:28:52PM +0300, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > So while reviewing the NV12 stuff it became clear to me no one
> > > had really given fb->offsets[] handling any serious thought.
> > > So this patch series aims to fix that. We now treat fb->offsets[]
> > > as a linear offset always. One clear benefit over treating it as
> > > a linear offset as opposed to a raw byte offset is that we don't
> > > have to think about the layout of bytes within the tile at all.
> > > 
> > > The series also generalizes the page rotation to be format agnostic,
> > > the caller just specifies the desired geometry in pages for each
> > > plane, and the rotation code builds up the sg. The intel_rotation_info
> > > then just contains the minimal amount of information needed to
> > > do the page rotation.
> > > 
> > > SKL+ also gets changed to use the compute_page_offset stuff so that
> > > the plane SURF register will contain the closes (properly aligned)
> > > page boundary, and the x/y offsets deal with whatever is left over.
> > > The plane code for the other platforms also gets simpler in the end
> > > I think. Also the 90/270 rotation handling becomes rather trivial
> > > for the plane code.
> > > 
> > > I should still write some decent tests to exercise fb->offsets[].
> > > 
> > > Series available here:
> > > git://github.com/vsyrjala/linux.git fb_offsets
> > 
> > As mentioned on irc patches 13&14 need to me unified with my 3 patch
> > series, but otherwise lgtm overall.
> 
> Ok done a review pass and I think I unconfused myself about the bytes vs.
> pixels fun. Imo that really needs to be a lot more explicit. My
> suggestion:
> 
> - tile_width, tile_height, pixel_stride: always pixels
> - tile_pitch, pitch: always bytes
> 
> And instead of silently changing units just use new variables. gcc will
> clean it up. I'm totally ok with doing that as a follow-up.
> 
> I didn't review the 2nd last patch in detail since -ETOOBIG.

Another thing that crossed my mind: do we have testcase for rotated 16bpp
framebuffers? All the confusion between pixels and bytes and my confusion
with Yf tiling suggests that might be useful.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-21 14:22           ` Ville Syrjälä
@ 2015-10-21 15:20             ` Daniel Vetter
  2015-10-21 15:42               ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Daniel Vetter @ 2015-10-21 15:20 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 05:22:40PM +0300, Ville Syrjälä wrote:
> On Wed, Oct 21, 2015 at 02:22:10PM +0100, Tvrtko Ursulin wrote:
> > 
> > On 21/10/15 14:09, Ville Syrjälä wrote:
> > > On Wed, Oct 21, 2015 at 01:17:10PM +0100, Tvrtko Ursulin wrote:
> > >>
> > >> On 21/10/15 12:28, Daniel Vetter wrote:
> > >>> On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> > >>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >>>>
> > >>>> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> > >>>> rotation (to find the right GTT view for it), so no need to pass all
> > >>>> kinds of plane stuff.
> > >>>>
> > >>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >>>
> > >>> Feels indeed a bit like a bikeshed and just churn without resolving the
> > >>> "pass vma in plane_state around" idea for real. But meh, it's imo not
> > >>> worse than the existing code, and looks correct. Less churn would make me
> > >>> a happier reviewer thought (there's a pile of whitespace in here too).
> > >>>
> > >>> Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > >>
> > >> It is worse, and is definitely not better. :(
> > >
> > > I might accept that if it wasn't for the ugly 'if (!plane_state)' mess.
> > 
> > Ok you have a point there. Maybe there should be a fake default state 
> > available, if somehow possible? Would all zero be a valid state?
> 
> Let's not start adding fake stuff, that's going to be even more
> confusing. IMO the correct approach is to have a low level function that
> doesn't depend on the state (which is what we have after my patch more or
> less), and then we can just wrap it up in nicer clothing for most normal
> users.

I agree, my only complaint is that it's hard to judge the low-level polish
without the pretty clothes on top ;-)

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
  2015-10-21 15:20             ` Daniel Vetter
@ 2015-10-21 15:42               ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2015-10-21 15:42 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Wed, Oct 21, 2015 at 05:20:02PM +0200, Daniel Vetter wrote:
> On Wed, Oct 21, 2015 at 05:22:40PM +0300, Ville Syrjälä wrote:
> > On Wed, Oct 21, 2015 at 02:22:10PM +0100, Tvrtko Ursulin wrote:
> > > 
> > > On 21/10/15 14:09, Ville Syrjälä wrote:
> > > > On Wed, Oct 21, 2015 at 01:17:10PM +0100, Tvrtko Ursulin wrote:
> > > >>
> > > >> On 21/10/15 12:28, Daniel Vetter wrote:
> > > >>> On Wed, Oct 14, 2015 at 07:29:03PM +0300, ville.syrjala@linux.intel.com wrote:
> > > >>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > >>>>
> > > >>>> intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird
> > > >>>> rotation (to find the right GTT view for it), so no need to pass all
> > > >>>> kinds of plane stuff.
> > > >>>>
> > > >>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > >>>
> > > >>> Feels indeed a bit like a bikeshed and just churn without resolving the
> > > >>> "pass vma in plane_state around" idea for real. But meh, it's imo not
> > > >>> worse than the existing code, and looks correct. Less churn would make me
> > > >>> a happier reviewer thought (there's a pile of whitespace in here too).
> > > >>>
> > > >>> Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > > >>
> > > >> It is worse, and is definitely not better. :(
> > > >
> > > > I might accept that if it wasn't for the ugly 'if (!plane_state)' mess.
> > > 
> > > Ok you have a point there. Maybe there should be a fake default state 
> > > available, if somehow possible? Would all zero be a valid state?
> > 
> > Let's not start adding fake stuff, that's going to be even more
> > confusing. IMO the correct approach is to have a low level function that
> > doesn't depend on the state (which is what we have after my patch more or
> > less), and then we can just wrap it up in nicer clothing for most normal
> > users.
> 
> I agree, my only complaint is that it's hard to judge the low-level polish
> without the pretty clothes on top ;-)

Quality tailoring requires decent measurements, or we might end up with
a clown costume instead of a nice suit. At least I haven't really thought
through what we really want here.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

end of thread, other threads:[~2015-10-21 15:43 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-14 16:28 [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic ville.syrjala
2015-10-14 16:28 ` [PATCH 01/22] drm: Add drm_format_plane_width() and drm_format_plane_height() ville.syrjala
2015-10-21  9:53   ` Daniel Vetter
2015-10-14 16:28 ` [PATCH 02/22] drm/i915: Pass modifier instead of tiling_mode to gen4_compute_page_offset() ville.syrjala
2015-10-21  9:54   ` Daniel Vetter
2015-10-14 16:28 ` [PATCH 03/22] drm/i915: Factor out intel_tile_width() ville.syrjala
2015-10-21 10:15   ` Daniel Vetter
2015-10-21 12:09     ` Ville Syrjälä
2015-10-21 12:16       ` Daniel Vetter
2015-10-14 16:28 ` [PATCH 04/22] drm/i915: Redo intel_tile_height() as intel_tile_size() / intel_tile_width() ville.syrjala
2015-10-21 10:21   ` Daniel Vetter
2015-10-14 16:28 ` [PATCH 05/22] drm/i915: change intel_fill_fb_ggtt_view() to use the real tile size ville.syrjala
2015-10-21 10:22   ` Daniel Vetter
2015-10-14 16:28 ` [PATCH 06/22] drm/i915: Use intel_tile_{size, width, height}() in intel_gen4_compute_page_offset() ville.syrjala
2015-10-21 10:24   ` Daniel Vetter
2015-10-14 16:28 ` [PATCH 07/22] drm/i915: s/intel_gen4_compute_page_offset/intel_compute_page_offset/ ville.syrjala
2015-10-21 10:45   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 08/22] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
2015-10-21 10:53   ` Daniel Vetter
2015-10-21 11:36     ` Ville Syrjälä
2015-10-21 12:11       ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 09/22] drm/i915: Refactor intel_surf_alignment() ville.syrjala
2015-10-21 10:54   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 10/22] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
2015-10-21 11:22   ` Daniel Vetter
2015-10-21 11:32     ` Daniel Vetter
2015-10-21 11:39     ` Ville Syrjälä
2015-10-14 16:29 ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
2015-10-15  9:08   ` Chris Wilson
2015-10-15  9:36     ` Ville Syrjälä
2015-10-15 10:05       ` Daniel Vetter
2015-10-15 10:47         ` [PATCH] drm/i915: Split out aliasing-ppgtt from ggtt_bind_vma() Chris Wilson
2015-10-15 11:10   ` [PATCH 11/22] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() Tvrtko Ursulin
2015-10-15 11:17     ` Ville Syrjälä
2015-10-15 11:30       ` Tvrtko Ursulin
2015-10-15 12:11         ` Ville Syrjälä
2015-10-21 11:28   ` Daniel Vetter
2015-10-21 12:17     ` Tvrtko Ursulin
2015-10-21 13:09       ` Ville Syrjälä
2015-10-21 13:22         ` Tvrtko Ursulin
2015-10-21 14:22           ` Ville Syrjälä
2015-10-21 15:20             ` Daniel Vetter
2015-10-21 15:42               ` Ville Syrjälä
2015-10-14 16:29 ` [PATCH 12/22] drm/i915: Set i915_ggtt_view_normal type explicitly ville.syrjala
2015-10-15 11:15   ` Tvrtko Ursulin
2015-10-15 12:01     ` Daniel Vetter
2015-10-21 11:28       ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 13/22] drm/i915: Move the partial and rotated view data into the same union ville.syrjala
2015-10-21 11:30   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 14/22] drm/i915: Don't treat differently sized rotated views as equal ville.syrjala
2015-10-15 11:18   ` Tvrtko Ursulin
2015-10-15 12:02     ` Daniel Vetter
2015-10-15 12:06       ` Ville Syrjälä
2015-10-15 12:24         ` Daniel Vetter
2015-10-21 13:06           ` Ville Syrjälä
2015-10-21 11:36   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 15/22] drm/i915: Pass the dma_addr_t array as const to rotate_pages() ville.syrjala
2015-10-21 11:36   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 16/22] drm/i915: Pass stride " ville.syrjala
2015-10-14 16:29 ` [PATCH 17/22] drm/i915: Pass rotation_info to intel_rotate_fb_obj_pages() ville.syrjala
2015-10-14 16:29 ` [PATCH 18/22] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
2015-10-14 16:43   ` Daniel Vetter
2015-10-21 11:41   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 19/22] drm/i915: Don't leak framebuffer_references if drm_framebuffer_init() fails ville.syrjala
2015-10-21 11:42   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 20/22] drm/i915: Pass drm_frambuffer to intel_compute_page_offset() ville.syrjala
2015-10-21 11:43   ` Daniel Vetter
2015-10-14 16:29 ` [PATCH 21/22] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
2015-10-15 17:59   ` [PATCH v2 " ville.syrjala
2015-10-21 12:01     ` Daniel Vetter
2015-10-21 14:19       ` Ville Syrjälä
2015-10-14 16:29 ` [PATCH 22/22] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
2015-10-21 12:06   ` Daniel Vetter
2015-10-14 16:59 ` [PATCH 00/22] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic Daniel Vetter
2015-10-21 12:09   ` Daniel Vetter
2015-10-21 15:15     ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.