* [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3)
@ 2016-02-15 20:54 ville.syrjala
2016-02-15 20:54 ` [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view ville.syrjala
` (21 more replies)
0 siblings, 22 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Another iteration of the fb offset stuff. Unfortunately this seems
to be one of those things that just keeps on growing when you're
not looking. But I'm hoping we're starting to approach the limit.
Changes from the last time [1]:
* split the chrome plane vma size fix from one of the other patches
* shuffling the bytes vs. pixels vs. tiles stuff around
* extracted a few more pieces of common code
* deal with fence vs. fb offset alignment better
* deal with SKL X-tile fail
* add preliminary NV12 AUX_DIST handling
* possible something else I've forgotten
I also have a few testcases lying around somewhere, but I'll need to
clean those up somewhat before I post them.
Entire lot (+ a few extras on top) available here:
git://github.com/vsyrjala/linux.git fb_offsets_14
[1] https://lists.freedesktop.org/archives/intel-gfx/2016-January/085802.html
Ville Syrjälä (21):
drm/i915: Account for the size of the chroma plane for the rotated gtt
view
drm/i915: s/tile_width/tile_width_bytes/
drm/i915: Pass 90/270 vs. 0/180 rotation info for
intel_gen4_compute_page_offset()
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: Pass drm_frambuffer to intel_compute_page_offset()
drm/i915: Reorganize intel_rotation_info
drm/i915: Move the NULL sg handling out from rotate_pages()
drm/i915: Embed rotation_info under intel_framebuffer
drm/i915: Rewrite fb rotation GTT handling
drm/i915: Don't pass pitch to intel_compute_page_offset()
drm/i915: Move SKL hw stride calculation into a helper
drm/i915: Pass around plane_state instead of fb+rotation
drm/i915: Use fb modifiers for display tiling decisions
drm/i915: Adjust obj tiling vs. fb modifier rules
drm/i915: Limit fb x offset due to fences
drm/i915: Allow calling intel_adjust_tile_offset() multiple times
drm/i915: Make intel_adjust_tile_offset() work for linear buffers
drm/i915: Compute display surface offset in the plane check hook for
SKL+
drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+
drm/i915: Make sure fb offset is (macro)pixel aligned
drivers/gpu/drm/i915/i915_gem_gtt.c | 64 +--
drivers/gpu/drm/i915/i915_gem_gtt.h | 14 +-
drivers/gpu/drm/i915/intel_display.c | 924 +++++++++++++++++++++++++++--------
drivers/gpu/drm/i915/intel_drv.h | 44 +-
drivers/gpu/drm/i915/intel_fbdev.c | 2 +-
drivers/gpu/drm/i915/intel_sprite.c | 126 ++---
6 files changed, 812 insertions(+), 362 deletions(-)
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-16 11:40 ` Tvrtko Ursulin
2016-02-17 12:51 ` Joonas Lahtinen
2016-02-15 20:54 ` [PATCH 02/21] drm/i915: s/tile_width/tile_width_bytes/ ville.syrjala
` (20 subsequent siblings)
21 siblings, 2 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
The size of the rotated ggtt mapping ought to include the size of the
chroma plane as well. Not a huge deal since we don't expose NV12 (or any
pother planar format for that matter) yet.
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Fixes: 9e759ff1f4a0 ("drm/i915: Return correct size for rotated views")
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 9127f8f3561c..4ccc8ec7003c 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3636,7 +3636,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->params.rotated.size;
+ return view->params.rotated.size + view->params.rotated.size_uv;
} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
return view->params.partial.size << PAGE_SHIFT;
} else {
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 02/21] drm/i915: s/tile_width/tile_width_bytes/
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
2016-02-15 20:54 ` [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-16 16:21 ` Daniel Vetter
2016-02-15 20:54 ` [PATCH v4 03/21] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
` (19 subsequent siblings)
21 siblings, 1 reply; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Make if clear whether we're talking tile widths in bytes or in pixels.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4d30bca0b26b..acc632c06135 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2222,8 +2222,8 @@ 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)
+static unsigned int intel_tile_width_bytes(const struct drm_i915_private *dev_priv,
+ uint64_t fb_modifier, unsigned int cpp)
{
switch (fb_modifier) {
case DRM_FORMAT_MOD_NONE:
@@ -2266,7 +2266,7 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
return 1;
else
return intel_tile_size(dev_priv) /
- intel_tile_width(dev_priv, fb_modifier, cpp);
+ intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
}
unsigned int
@@ -2285,7 +2285,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->params.rotated;
- unsigned int tile_size, tile_width, tile_height, cpp;
+ unsigned int tile_size, tile_width_bytes, tile_height, cpp;
*view = i915_ggtt_view_normal;
@@ -2306,19 +2306,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
tile_size = intel_tile_size(dev_priv);
cpp = drm_format_plane_cpp(fb->pixel_format, 0);
- tile_width = intel_tile_width(dev_priv, fb->modifier[0], cpp);
- tile_height = tile_size / tile_width;
+ tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[0], cpp);
+ tile_height = tile_size / tile_width_bytes;
- info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
+ info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width_bytes);
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;
+ tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[1], cpp);
+ tile_height = tile_size / tile_width_bytes;
- info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
+ info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width_bytes);
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;
}
@@ -2455,18 +2455,18 @@ u32 intel_compute_tile_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_size, tile_width_bytes, tile_height;
unsigned int tile_rows, tiles;
tile_size = intel_tile_size(dev_priv);
- tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
- tile_height = tile_size / tile_width;
+ tile_width_bytes = intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
+ tile_height = tile_size / tile_width_bytes;
tile_rows = *y / tile_height;
*y %= tile_height;
- tiles = *x / (tile_width/cpp);
- *x %= tile_width/cpp;
+ tiles = *x / (tile_width_bytes/cpp);
+ *x %= tile_width_bytes/cpp;
return tile_rows * pitch * tile_height + tiles * tile_size;
} else {
@@ -2928,7 +2928,7 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
} else {
int cpp = drm_format_plane_cpp(pixel_format, 0);
- return intel_tile_width(dev_priv, fb_modifier, cpp);
+ return intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
}
}
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v4 03/21] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
2016-02-15 20:54 ` [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view ville.syrjala
2016-02-15 20:54 ` [PATCH 02/21] drm/i915: s/tile_width/tile_width_bytes/ ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-16 16:23 ` Daniel Vetter
2016-02-15 20:54 ` [PATCH v3 04/21] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
` (18 subsequent siblings)
21 siblings, 1 reply; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 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
v3: Introduce intel_tile_dims(), and don't mix up different units so much
v4: Unconfuse bytes vs. pixels even more
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 72 +++++++++++++++++++++++++-----------
drivers/gpu/drm/i915/intel_drv.h | 3 +-
drivers/gpu/drm/i915/intel_sprite.c | 18 +++++----
3 files changed, 63 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index acc632c06135..dcf379c29523 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2269,6 +2269,20 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
}
+/* Return the tile dimensions in pixel units */
+static void intel_tile_dims(const struct drm_i915_private *dev_priv,
+ unsigned int *tile_width,
+ unsigned int *tile_height,
+ uint64_t fb_modifier,
+ unsigned int cpp)
+{
+ unsigned int tile_width_bytes =
+ intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
+
+ *tile_width = tile_width_bytes / cpp;
+ *tile_height = intel_tile_size(dev_priv) / tile_width_bytes;
+}
+
unsigned int
intel_fb_align_height(struct drm_device *dev, unsigned int height,
uint32_t pixel_format, uint64_t fb_modifier)
@@ -2285,7 +2299,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->params.rotated;
- unsigned int tile_size, tile_width_bytes, tile_height, cpp;
+ unsigned int tile_size, tile_width, tile_height, cpp;
*view = i915_ggtt_view_normal;
@@ -2306,19 +2320,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
tile_size = intel_tile_size(dev_priv);
cpp = drm_format_plane_cpp(fb->pixel_format, 0);
- tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[0], cpp);
- tile_height = tile_size / tile_width_bytes;
+ intel_tile_dims(dev_priv, &tile_width, &tile_height,
+ fb->modifier[0], cpp);
- info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width_bytes);
+ info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
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_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[1], cpp);
- tile_height = tile_size / tile_width_bytes;
+ intel_tile_dims(dev_priv, &tile_width, &tile_height,
+ fb->modifier[1], cpp);
- info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width_bytes);
+ info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
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;
}
@@ -2446,29 +2460,43 @@ 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. */
+/*
+ * 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.
+ */
u32 intel_compute_tile_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_bytes, tile_height;
- unsigned int tile_rows, tiles;
+ unsigned int tile_size, tile_width, tile_height;
+ unsigned int tile_rows, tiles, pitch_tiles;
tile_size = intel_tile_size(dev_priv);
- tile_width_bytes = intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
- tile_height = tile_size / tile_width_bytes;
+ intel_tile_dims(dev_priv, &tile_width, &tile_height,
+ fb_modifier, cpp);
+
+ if (intel_rotation_90_or_270(rotation)) {
+ pitch_tiles = pitch / tile_height;
+ swap(tile_width, tile_height);
+ } else {
+ pitch_tiles = pitch / (tile_width * cpp);
+ }
tile_rows = *y / tile_height;
*y %= tile_height;
- tiles = *x / (tile_width_bytes/cpp);
- *x %= tile_width_bytes/cpp;
+ tiles = *x / tile_width;
+ *x %= tile_width;
- return tile_rows * pitch * tile_height + tiles * tile_size;
+ return (tile_rows * pitch_tiles + tiles) * tile_size;
} else {
unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
unsigned int offset;
@@ -2713,6 +2741,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
u32 linear_offset;
u32 dspcntr;
i915_reg_t reg = DSPCNTR(plane);
+ unsigned int rotation = plane_state->base.rotation;
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
int x = plane_state->src.x1 >> 16;
int y = plane_state->src.y1 >> 16;
@@ -2779,13 +2808,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
intel_crtc->dspaddr_offset =
intel_compute_tile_offset(dev_priv, &x, &y,
fb->modifier[0], cpp,
- fb->pitches[0]);
+ fb->pitches[0], rotation);
linear_offset -= intel_crtc->dspaddr_offset;
} else {
intel_crtc->dspaddr_offset = linear_offset;
}
- if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+ if (rotation == BIT(DRM_ROTATE_180)) {
dspcntr |= DISPPLANE_ROTATE_180;
x += (crtc_state->pipe_src_w - 1);
@@ -2843,6 +2872,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
u32 linear_offset;
u32 dspcntr;
i915_reg_t reg = DSPCNTR(plane);
+ unsigned int rotation = plane_state->base.rotation;
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
int x = plane_state->src.x1 >> 16;
int y = plane_state->src.y1 >> 16;
@@ -2886,9 +2916,9 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
intel_crtc->dspaddr_offset =
intel_compute_tile_offset(dev_priv, &x, &y,
fb->modifier[0], cpp,
- fb->pitches[0]);
+ fb->pitches[0], rotation);
linear_offset -= intel_crtc->dspaddr_offset;
- if (plane_state->base.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 3cae3768ea37..7992e7a974f4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1177,7 +1177,8 @@ u32 intel_compute_tile_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 a2582c455b36..7dc2b8b2a4ac 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -193,7 +193,7 @@ skl_update_plane(struct drm_plane *drm_plane,
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
u32 surf_addr;
u32 tile_height, plane_offset, plane_size;
- unsigned int rotation;
+ unsigned int rotation = plane_state->base.rotation;
int x_offset, y_offset;
int crtc_x = plane_state->dst.x1;
int crtc_y = plane_state->dst.y1;
@@ -213,7 +213,6 @@ skl_update_plane(struct drm_plane *drm_plane,
plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
- rotation = plane_state->base.rotation;
plane_ctl |= skl_plane_ctl_rotation(rotation);
stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
@@ -351,6 +350,7 @@ vlv_update_plane(struct drm_plane *dplane,
int plane = intel_plane->plane;
u32 sprctl;
u32 sprsurf_offset, linear_offset;
+ unsigned int rotation = dplane->state->rotation;
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
int crtc_x = plane_state->dst.x1;
@@ -425,10 +425,10 @@ vlv_update_plane(struct drm_plane *dplane,
linear_offset = y * fb->pitches[0] + x * cpp;
sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
fb->modifier[0], cpp,
- fb->pitches[0]);
+ fb->pitches[0], rotation);
linear_offset -= sprsurf_offset;
- if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+ if (rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SP_ROTATE_180;
x += src_w;
@@ -493,6 +493,7 @@ ivb_update_plane(struct drm_plane *plane,
enum pipe pipe = intel_plane->pipe;
u32 sprctl, sprscale = 0;
u32 sprsurf_offset, linear_offset;
+ unsigned int rotation = plane_state->base.rotation;
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
int crtc_x = plane_state->dst.x1;
@@ -558,10 +559,10 @@ ivb_update_plane(struct drm_plane *plane,
linear_offset = y * fb->pitches[0] + x * cpp;
sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
fb->modifier[0], cpp,
- fb->pitches[0]);
+ fb->pitches[0], rotation);
linear_offset -= sprsurf_offset;
- if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+ if (rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SPRITE_ROTATE_180;
/* HSW and BDW does this automagically in hardware */
@@ -634,6 +635,7 @@ ilk_update_plane(struct drm_plane *plane,
int pipe = intel_plane->pipe;
u32 dvscntr, dvsscale;
u32 dvssurf_offset, linear_offset;
+ unsigned int rotation = plane_state->base.rotation;
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
int crtc_x = plane_state->dst.x1;
@@ -695,10 +697,10 @@ ilk_update_plane(struct drm_plane *plane,
linear_offset = y * fb->pitches[0] + x * cpp;
dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
fb->modifier[0], cpp,
- fb->pitches[0]);
+ fb->pitches[0], rotation);
linear_offset -= dvssurf_offset;
- if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+ if (rotation == BIT(DRM_ROTATE_180)) {
dvscntr |= DVS_ROTATE_180;
x += src_w;
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v3 04/21] drm/i915: Support for extra alignment for tiled surfaces
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (2 preceding siblings ...)
2016-02-15 20:54 ` [PATCH v4 03/21] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-16 16:26 ` Daniel Vetter
2016-02-15 20:54 ` [PATCH v2 05/21] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
` (17 subsequent siblings)
21 siblings, 1 reply; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 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.
v2: Be less confusing wrt. units (pixels vs. bytes) (Daniel)
v3: Use u32 for offsets
Have intel_adjust_tile_offset() return the new offset (will be
useful later)
Add an offset_aligned variable (Daniel)
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 50 ++++++++++++++++++++++++++++++++----
1 file changed, 45 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dcf379c29523..fe8d534a3334 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2461,6 +2461,35 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
}
/*
+ * Adjust the tile offset by moving the difference into
+ * the x/y offsets.
+ *
+ * Input tile dimensions and pitch must already be
+ * rotated to match x and y, and in pixel units.
+ */
+static u32 intel_adjust_tile_offset(int *x, int *y,
+ unsigned int tile_width,
+ unsigned int tile_height,
+ unsigned int tile_size,
+ unsigned int pitch_tiles,
+ u32 old_offset,
+ u32 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;
+
+ *y += tiles / pitch_tiles * tile_height;
+ *x += tiles % pitch_tiles * tile_width;
+
+ return new_offset;
+}
+
+/*
* Computes the linear offset to the base tile and adjusts
* x, y. bytes per pixel is assumed to be a power-of-two.
*
@@ -2475,6 +2504,12 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
unsigned int pitch,
unsigned int rotation)
{
+ u32 offset, offset_aligned, 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, pitch_tiles;
@@ -2496,16 +2531,21 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
tiles = *x / tile_width;
*x %= tile_width;
- return (tile_rows * pitch_tiles + tiles) * tile_size;
- } else {
- unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
- unsigned int offset;
+ offset = (tile_rows * pitch_tiles + tiles) * tile_size;
+ offset_aligned = offset & ~alignment;
+ intel_adjust_tile_offset(x, y, tile_width, tile_height,
+ tile_size, pitch_tiles,
+ offset, offset_aligned);
+ } else {
offset = *y * pitch + *x * cpp;
+ offset_aligned = offset & ~alignment;
+
*y = (offset & alignment) / pitch;
*x = ((offset & alignment) - *y * pitch) / cpp;
- return offset & ~alignment;
}
+
+ return offset_aligned;
}
static int i9xx_format_to_fourcc(int format)
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v2 05/21] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (3 preceding siblings ...)
2016-02-15 20:54 ` [PATCH v3 04/21] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 06/21] drm/i915: Pass drm_frambuffer to intel_compute_page_offset() ville.syrjala
` (16 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 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.
The main motivation is to get rid of the uggy NULL plane_state handling
due to fbdev.
v2: Add a note why I really want this
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Grumpily-Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
drivers/gpu/drm/i915/intel_display.c | 41 +++++++++++++++---------------------
drivers/gpu/drm/i915/intel_drv.h | 5 ++---
drivers/gpu/drm/i915/intel_fbdev.c | 2 +-
3 files changed, 20 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fe8d534a3334..15634d9cb666 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2294,8 +2294,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
}
static void
-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->params.rotated;
@@ -2303,10 +2304,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
*view = i915_ggtt_view_normal;
- if (!plane_state)
- return;
-
- if (!intel_rotation_90_or_270(plane_state->rotation))
+ if (!intel_rotation_90_or_270(rotation))
return;
*view = i915_ggtt_view_rotated;
@@ -2371,9 +2369,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 drm_device *dev = fb->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2386,7 +2383,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
- intel_fill_fb_ggtt_view(&view, fb, plane_state);
+ 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
@@ -2444,15 +2441,14 @@ err_pm:
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;
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
- intel_fill_fb_ggtt_view(&view, fb, plane_state);
+ intel_fill_fb_ggtt_view(&view, fb, rotation);
if (view.type == I915_GGTT_VIEW_NORMAL)
i915_gem_object_unpin_fence(obj);
@@ -3011,7 +3007,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
u64 offset;
intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
- intel_plane->base.state);
+ intel_plane->base.state->rotation);
vma = i915_gem_obj_to_ggtt_view(obj, &view);
if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
@@ -10980,7 +10976,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)
@@ -11746,8 +11742,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup_pending;
}
- ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
- crtc->primary->state);
+ ret = intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
if (ret)
goto cleanup_pending;
@@ -11797,7 +11792,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 (!IS_ERR_OR_NULL(request))
i915_gem_request_cancel(request);
@@ -13909,7 +13904,7 @@ 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);
+ ret = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
}
if (ret == 0) {
@@ -13953,7 +13948,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
!INTEL_INFO(dev)->cursor_needs_physical))
- intel_unpin_fb_obj(old_state->fb, old_state);
+ intel_unpin_fb_obj(old_state->fb, old_state->rotation);
/* prepare_fb aborted? */
if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
@@ -13961,7 +13956,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
i915_gem_request_assign(&old_intel_state->wait_req, NULL);
-
}
int
@@ -16058,9 +16052,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);
mutex_unlock(&dev->struct_mutex);
if (ret) {
DRM_ERROR("failed to pin boot fb on pipe %d\n",
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7992e7a974f4..cb17e1f28e2c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1107,9 +1107,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 drm_framebuffer *
__intel_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 09840f4380f9..082deb31c900 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -220,7 +220,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
* This also validates that any existing fb inherited from the
* BIOS is suitable for own access.
*/
- ret = intel_pin_and_fence_fb_obj(NULL, &ifbdev->fb->base, NULL);
+ ret = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
if (ret)
goto out_unlock;
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 06/21] drm/i915: Pass drm_frambuffer to intel_compute_page_offset()
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (4 preceding siblings ...)
2016-02-15 20:54 ` [PATCH v2 05/21] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH v2 07/21] drm/i915: Reorganize intel_rotation_info ville.syrjala
` (15 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 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>
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 15634d9cb666..523e75e536dd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2493,13 +2493,14 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
* to be already rotated to match the rotated GTT view, and
* pitch is the tile_height aligned framebuffer height.
*/
-u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
- int *x, int *y,
- uint64_t fb_modifier,
- unsigned int cpp,
+u32 intel_compute_tile_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);
u32 offset, offset_aligned, alignment;
alignment = intel_surf_alignment(dev_priv, fb_modifier);
@@ -2842,8 +2843,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
if (INTEL_INFO(dev)->gen >= 4) {
intel_crtc->dspaddr_offset =
- intel_compute_tile_offset(dev_priv, &x, &y,
- fb->modifier[0], cpp,
+ intel_compute_tile_offset(&x, &y, fb, 0,
fb->pitches[0], rotation);
linear_offset -= intel_crtc->dspaddr_offset;
} else {
@@ -2950,8 +2950,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
linear_offset = y * fb->pitches[0] + x * cpp;
intel_crtc->dspaddr_offset =
- intel_compute_tile_offset(dev_priv, &x, &y,
- fb->modifier[0], cpp,
+ intel_compute_tile_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 cb17e1f28e2c..1d3ed21addb4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1172,10 +1172,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)
-u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
- int *x, int *y,
- uint64_t fb_modifier,
- unsigned int cpp,
+u32 intel_compute_tile_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 7dc2b8b2a4ac..8821533561b1 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -423,8 +423,7 @@ vlv_update_plane(struct drm_plane *dplane,
crtc_h--;
linear_offset = y * fb->pitches[0] + x * cpp;
- sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
- fb->modifier[0], cpp,
+ sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
fb->pitches[0], rotation);
linear_offset -= sprsurf_offset;
@@ -557,8 +556,7 @@ ivb_update_plane(struct drm_plane *plane,
sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
linear_offset = y * fb->pitches[0] + x * cpp;
- sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
- fb->modifier[0], cpp,
+ sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
fb->pitches[0], rotation);
linear_offset -= sprsurf_offset;
@@ -695,8 +693,7 @@ ilk_update_plane(struct drm_plane *plane,
dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
linear_offset = y * fb->pitches[0] + x * cpp;
- dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
- fb->modifier[0], cpp,
+ dvssurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
fb->pitches[0], rotation);
linear_offset -= dvssurf_offset;
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v2 07/21] drm/i915: Reorganize intel_rotation_info
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (5 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 06/21] drm/i915: Pass drm_frambuffer to intel_compute_page_offset() ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 08/21] drm/i915: Move the NULL sg handling out from rotate_pages() ville.syrjala
` (14 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Throw out a bunch of unnecessary stuff from struct intel_rotation_info,
and pull most of the remaining stuff to live under an array of
per-color plane sub-structures.
What still remains outside the sub-structure will be reorgranized later
as well, but that requires more work elsewhere so leave it be for now.
v2: Split the vma size == luma+chroma size fix to prep patch (Daniel)
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1)
---
drivers/gpu/drm/i915/i915_gem_gtt.c | 35 +++++++++++++++--------------------
drivers/gpu/drm/i915/i915_gem_gtt.h | 11 ++++-------
drivers/gpu/drm/i915/intel_display.c | 25 +++++++++++++++----------
drivers/gpu/drm/i915/intel_drv.h | 1 +
4 files changed, 35 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 4ccc8ec7003c..27a3e17f2882 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3403,7 +3403,7 @@ static struct sg_table *
intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
struct drm_i915_gem_object *obj)
{
- unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
+ unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height;
unsigned int size_pages_uv;
struct sg_page_iter sg_iter;
unsigned long i;
@@ -3421,7 +3421,7 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
/* Account for UV plane with NV12. */
if (rot_info->pixel_format == DRM_FORMAT_NV12)
- size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
+ size_pages_uv = rot_info->plane[1].width * rot_info->plane[1].height;
else
size_pages_uv = 0;
@@ -3443,9 +3443,9 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
/* Rotate the pages. */
sg = rotate_pages(page_addr_list, 0,
- rot_info->width_pages, rot_info->height_pages,
- rot_info->width_pages,
- st, NULL);
+ rot_info->plane[0].width, rot_info->plane[0].height,
+ rot_info->plane[0].width,
+ st, NULL);
/* Append the UV plane if NV12. */
if (rot_info->pixel_format == DRM_FORMAT_NV12) {
@@ -3457,18 +3457,15 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
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,
+ rotate_pages(page_addr_list, rot_info->uv_start_page,
+ rot_info->plane[1].width, rot_info->plane[1].height,
+ rot_info->plane[1].width,
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,
+ DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
+ obj->base.size, rot_info->plane[0].width,
+ rot_info->plane[0].height, size_pages + size_pages_uv,
size_pages);
drm_free_large(page_addr_list);
@@ -3480,11 +3477,9 @@ 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,
+ DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%d) (%ux%u tiles, %u pages (%u plane 0))\n",
+ obj->base.size, ret, rot_info->plane[0].width,
+ rot_info->plane[0].height, size_pages + size_pages_uv,
size_pages);
return ERR_PTR(ret);
}
@@ -3636,7 +3631,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->params.rotated.size + view->params.rotated.size_uv;
+ return intel_rotation_info_size(&view->params.rotated) << PAGE_SHIFT;
} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
return view->params.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 66a6da2396a2..2fb98b1e4d82 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -135,16 +135,13 @@ 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;
+ } 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 523e75e536dd..74252433b1ec 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2293,6 +2293,17 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
return ALIGN(height, tile_height);
}
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info)
+{
+ unsigned int size = 0;
+ int i;
+
+ for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
+ size += rot_info->plane[i].width * rot_info->plane[i].height;
+
+ return size;
+}
+
static void
intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
const struct drm_framebuffer *fb,
@@ -2309,11 +2320,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
*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);
@@ -2321,18 +2328,16 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
intel_tile_dims(dev_priv, &tile_width, &tile_height,
fb->modifier[0], cpp);
- info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
- info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
- info->size = info->width_pages * info->height_pages * tile_size;
+ info->plane[0].width = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
+ info->plane[0].height = DIV_ROUND_UP(fb->height, tile_height);
if (info->pixel_format == DRM_FORMAT_NV12) {
cpp = drm_format_plane_cpp(fb->pixel_format, 1);
intel_tile_dims(dev_priv, &tile_width, &tile_height,
fb->modifier[1], cpp);
- info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
- 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;
+ info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
+ info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
}
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1d3ed21addb4..59bed59388ad 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1060,6 +1060,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
/* intel_display.c */
extern const struct drm_plane_funcs intel_plane_funcs;
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
bool intel_has_pending_fb_unpin(struct drm_device *dev);
int intel_pch_rawclk(struct drm_device *dev);
int intel_hrawclk(struct drm_device *dev);
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 08/21] drm/i915: Move the NULL sg handling out from rotate_pages()
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (6 preceding siblings ...)
2016-02-15 20:54 ` [PATCH v2 07/21] drm/i915: Reorganize intel_rotation_info ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 09/21] drm/i915: Embed rotation_info under intel_framebuffer ville.syrjala
` (13 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
rotate_pages() checks to see if it got called with a NULL sg, and then
goes to extract it from sg->sgl. It always gets called with a NULL sg
for the first plane, so moving the initial 'sg=st->sgl' assignment out
into intel_rotate_fb_obj_pages() seems less special-casey.
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 | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 27a3e17f2882..51f2597e3c56 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3375,11 +3375,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++) {
@@ -3441,11 +3436,14 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
i++;
}
+ st->nents = 0;
+ sg = st->sgl;
+
/* Rotate the pages. */
sg = rotate_pages(page_addr_list, 0,
rot_info->plane[0].width, rot_info->plane[0].height,
rot_info->plane[0].width,
- st, NULL);
+ st, sg);
/* Append the UV plane if NV12. */
if (rot_info->pixel_format == DRM_FORMAT_NV12) {
@@ -3457,10 +3455,10 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
rot_info->uv_start_page = uv_start_page;
- rotate_pages(page_addr_list, rot_info->uv_start_page,
- rot_info->plane[1].width, rot_info->plane[1].height,
- rot_info->plane[1].width,
- st, sg);
+ sg = rotate_pages(page_addr_list, rot_info->uv_start_page,
+ rot_info->plane[1].width, rot_info->plane[1].height,
+ rot_info->plane[1].width,
+ st, sg);
}
DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 09/21] drm/i915: Embed rotation_info under intel_framebuffer
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (7 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 08/21] drm/i915: Move the NULL sg handling out from rotate_pages() ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-03-01 11:00 ` Ville Syrjälä
2016-02-15 20:54 ` [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
` (12 subsequent siblings)
21 siblings, 1 reply; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Instead of repopulatin the rotation_info struct for the fb every time
we try to use the fb, we can just populate it once when creating the fb,
and later we can just copy the pre-populate struct into the gtt_view.
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 | 27 ++++++++++++++++-----------
drivers/gpu/drm/i915/intel_drv.h | 1 +
2 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 74252433b1ec..fddfc5875752 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2309,18 +2309,20 @@ 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->params.rotated;
- unsigned int tile_size, tile_width, tile_height, cpp;
-
- *view = i915_ggtt_view_normal;
-
- if (!intel_rotation_90_or_270(rotation))
- return;
-
- *view = i915_ggtt_view_rotated;
+ if (intel_rotation_90_or_270(rotation)) {
+ *view = i915_ggtt_view_rotated;
+ view->params.rotated = to_intel_framebuffer(fb)->rot_info;
+ } else {
+ *view = i915_ggtt_view_normal;
+ }
+}
- info->uv_offset = fb->offsets[1];
+static void
+intel_fill_fb_info(struct drm_i915_private *dev_priv,
+ struct drm_framebuffer *fb)
+{
+ struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info;
+ unsigned int tile_size, tile_width, tile_height, cpp;
tile_size = intel_tile_size(dev_priv);
@@ -2336,6 +2338,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
intel_tile_dims(dev_priv, &tile_width, &tile_height,
fb->modifier[1], cpp);
+ info->uv_offset = fb->offsets[1];
info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
}
@@ -14891,6 +14894,8 @@ 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_fill_fb_info(dev_priv, &intel_fb->base);
+
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 59bed59388ad..674afa1f9f97 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -118,6 +118,7 @@ enum intel_output_type {
struct intel_framebuffer {
struct drm_framebuffer base;
struct drm_i915_gem_object *obj;
+ struct intel_rotation_info rot_info;
};
struct intel_fbdev {
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (8 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 09/21] drm/i915: Embed rotation_info under intel_framebuffer ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
[not found] ` <DBEE2697754A7A4EAA940D4FF7143C6250E38A75@BGSMSX102.gar.corp.intel.com>
2016-02-15 20:54 ` [PATCH v3 11/21] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
` (11 subsequent siblings)
21 siblings, 1 reply; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 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
v3: Split out more changes to prep patches (Daniel)
s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
Rename intel_surf_gtt_offset to intel_fb_gtt_offset
Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
v4: Fix alignment vs. alignment-1 when calling
_intel_compute_tile_offset() from intel_fill_fb_info()
Pass the pitch in tiles in
stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
Pass the full width/height of the rotated area to
drm_rect_rotate() for clarity
Use u32 for more offsets
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_gem_gtt.c | 51 ++---
drivers/gpu/drm/i915/i915_gem_gtt.h | 5 +-
drivers/gpu/drm/i915/intel_display.c | 373 +++++++++++++++++++++++------------
drivers/gpu/drm/i915/intel_drv.h | 19 +-
drivers/gpu/drm/i915/intel_sprite.c | 97 ++++-----
5 files changed, 331 insertions(+), 214 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 51f2597e3c56..5b17944a512b 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3395,16 +3395,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 *rot_info,
struct drm_i915_gem_object *obj)
{
- unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height;
- unsigned int size_pages_uv;
+ unsigned int size = intel_rotation_info_size(rot_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;
@@ -3414,18 +3412,12 @@ 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->plane[1].width * rot_info->plane[1].height;
- 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;
@@ -3439,32 +3431,14 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
st->nents = 0;
sg = st->sgl;
- /* Rotate the pages. */
- sg = rotate_pages(page_addr_list, 0,
- rot_info->plane[0].width, rot_info->plane[0].height,
- rot_info->plane[0].width,
- st, sg);
-
- /* 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;
-
- sg = rotate_pages(page_addr_list, rot_info->uv_start_page,
- rot_info->plane[1].width, rot_info->plane[1].height,
- rot_info->plane[1].width,
- st, sg);
+ for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++) {
+ sg = rotate_pages(page_addr_list, rot_info->plane[i].offset,
+ rot_info->plane[i].width, rot_info->plane[i].height,
+ rot_info->plane[i].stride, st, sg);
}
- DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
- obj->base.size, rot_info->plane[0].width,
- rot_info->plane[0].height, 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, rot_info->plane[0].width, rot_info->plane[0].height, size);
drm_free_large(page_addr_list);
@@ -3475,10 +3449,9 @@ 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) (%ux%u tiles, %u pages (%u plane 0))\n",
- obj->base.size, ret, rot_info->plane[0].width,
- rot_info->plane[0].height, 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, rot_info->plane[0].width, rot_info->plane[0].height, size);
+
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 2fb98b1e4d82..89f34a920338 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -135,12 +135,9 @@ enum i915_ggtt_view_type {
};
struct intel_rotation_info {
- unsigned int uv_offset;
- uint32_t pixel_format;
- unsigned int uv_start_page;
struct {
/* tiles */
- unsigned int width, height;
+ unsigned int width, height, stride, offset;
} plane[2];
};
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fddfc5875752..acd92f957054 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2317,33 +2317,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
}
}
-static void
-intel_fill_fb_info(struct drm_i915_private *dev_priv,
- struct drm_framebuffer *fb)
-{
- struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info;
- unsigned int tile_size, tile_width, tile_height, cpp;
-
- tile_size = intel_tile_size(dev_priv);
-
- cpp = drm_format_plane_cpp(fb->pixel_format, 0);
- intel_tile_dims(dev_priv, &tile_width, &tile_height,
- fb->modifier[0], cpp);
-
- info->plane[0].width = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
- info->plane[0].height = DIV_ROUND_UP(fb->height, tile_height);
-
- if (info->pixel_format == DRM_FORMAT_NV12) {
- cpp = drm_format_plane_cpp(fb->pixel_format, 1);
- intel_tile_dims(dev_priv, &tile_width, &tile_height,
- fb->modifier[1], cpp);
-
- info->uv_offset = fb->offsets[1];
- info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
- info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
- }
-}
-
static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
{
if (INTEL_INFO(dev_priv)->gen >= 9)
@@ -2465,6 +2438,42 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation
}
/*
+ * 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.
+ */
+u32 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;
+}
+
+/*
+ * 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 intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+ if (intel_rotation_90_or_270(rotation)) {
+ *x += intel_fb->rotated[plane].x;
+ *y += intel_fb->rotated[plane].y;
+ } else {
+ *x += intel_fb->normal[plane].x;
+ *y += intel_fb->normal[plane].y;
+ }
+}
+
+/*
* Adjust the tile offset by moving the difference into
* the x/y offsets.
*
@@ -2500,18 +2509,24 @@ static u32 intel_adjust_tile_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.
*/
-u32 intel_compute_tile_offset(int *x, int *y,
- const struct drm_framebuffer *fb, int plane,
- unsigned int pitch,
- unsigned int rotation)
+static u32 _intel_compute_tile_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,
+ u32 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);
- u32 offset, offset_aligned, alignment;
+ u32 offset, offset_aligned;
- alignment = intel_surf_alignment(dev_priv, fb_modifier);
if (alignment)
alignment--;
@@ -2553,6 +2568,141 @@ u32 intel_compute_tile_offset(int *x, int *y,
return offset_aligned;
}
+u32 intel_compute_tile_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);
+ u32 alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
+
+ return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
+ rotation, alignment);
+}
+
+/* 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];
+ u32 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 *rot_info = &intel_fb->rot_info;
+ u32 gtt_offset_rotated = 0;
+ unsigned int max_size = 0;
+ uint32_t format = fb->pixel_format;
+ int i, num_planes = drm_format_num_planes(format);
+ unsigned int tile_size = intel_tile_size(dev_priv);
+
+ for (i = 0; i < num_planes; i++) {
+ unsigned int width, height;
+ unsigned int cpp, size;
+ u32 offset;
+ 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->normal[i].x = x;
+ intel_fb->normal[i].y = y;
+
+ offset = _intel_compute_tile_offset(dev_priv, &x, &y,
+ fb, 0, fb->pitches[i],
+ BIT(DRM_ROTATE_0), tile_size);
+ offset /= tile_size;
+
+ if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
+ unsigned int tile_width, tile_height;
+ unsigned int pitch_tiles;
+ struct drm_rect r;
+
+ intel_tile_dims(dev_priv, &tile_width, &tile_height,
+ fb->modifier[i], cpp);
+
+ rot_info->plane[i].offset = offset;
+ rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp);
+ rot_info->plane[i].width = DIV_ROUND_UP(x + width, tile_width);
+ rot_info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
+
+ intel_fb->rotated[i].pitch =
+ rot_info->plane[i].height * tile_height;
+
+ /* how many tiles does this plane need */
+ size = rot_info->plane[i].stride * rot_info->plane[i].height;
+ /*
+ * If the plane isn't horizontally tile aligned,
+ * we need one more tile.
+ */
+ if (x != 0)
+ size++;
+
+ /* 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,
+ rot_info->plane[i].width * tile_width,
+ rot_info->plane[i].height * tile_height,
+ BIT(DRM_ROTATE_270));
+ x = r.x1;
+ y = r.y1;
+
+ /* rotate the tile dimensions to match the GTT view */
+ pitch_tiles = intel_fb->rotated[i].pitch / tile_height;
+ swap(tile_width, tile_height);
+
+ /*
+ * We only keep the x/y offsets, so push all of the
+ * gtt offset into the x/y offsets.
+ */
+ intel_adjust_tile_offset(&x, &y, tile_size,
+ tile_width, tile_height, pitch_tiles,
+ gtt_offset_rotated * tile_size, 0);
+
+ gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height;
+
+ /*
+ * First pixel of the framebuffer from
+ * the start of the rotated gtt mapping.
+ */
+ intel_fb->rotated[i].x = x;
+ intel_fb->rotated[i].y = y;
+ } else {
+ size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
+ x * cpp, tile_size);
+ }
+
+ /* 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) {
@@ -2787,7 +2937,6 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
u32 dspcntr;
i915_reg_t reg = DSPCNTR(plane);
unsigned int rotation = plane_state->base.rotation;
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
int x = plane_state->src.x1 >> 16;
int y = plane_state->src.y1 >> 16;
@@ -2847,30 +2996,25 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
if (IS_G4X(dev))
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
- linear_offset = y * fb->pitches[0] + x * cpp;
+ 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_tile_offset(&x, &y, fb, 0,
fb->pitches[0], rotation);
- linear_offset -= intel_crtc->dspaddr_offset;
- } else {
- intel_crtc->dspaddr_offset = linear_offset;
- }
if (rotation == BIT(DRM_ROTATE_180)) {
dspcntr |= DISPPLANE_ROTATE_180;
x += (crtc_state->pipe_src_w - 1);
y += (crtc_state->pipe_src_h - 1);
-
- /* Finding the last pixel of the last line of the display
- data and adding to linear_offset*/
- linear_offset +=
- (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
- (crtc_state->pipe_src_w - 1) * cpp;
}
+ 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;
@@ -2879,7 +3023,8 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
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_fb_gtt_offset(fb, rotation) +
+ intel_crtc->dspaddr_offset);
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
I915_WRITE(DSPLINOFF(plane), linear_offset);
} else
@@ -2917,7 +3062,6 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
u32 dspcntr;
i915_reg_t reg = DSPCNTR(plane);
unsigned int rotation = plane_state->base.rotation;
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
int x = plane_state->src.x1 >> 16;
int y = plane_state->src.y1 >> 16;
@@ -2956,26 +3100,23 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
- linear_offset = y * fb->pitches[0] + x * cpp;
+ intel_add_fb_offsets(&x, &y, fb, 0, rotation);
+
intel_crtc->dspaddr_offset =
intel_compute_tile_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 += (crtc_state->pipe_src_w - 1);
y += (crtc_state->pipe_src_h - 1);
-
- /* Finding the last pixel of the last line of the display
- data and adding to linear_offset*/
- linear_offset +=
- (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
- (crtc_state->pipe_src_w - 1) * cpp;
}
}
+ linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+
intel_crtc->adjusted_x = x;
intel_crtc->adjusted_y = y;
@@ -2983,7 +3124,8 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
I915_WRITE(DSPSURF(plane),
- i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+ intel_fb_gtt_offset(fb, rotation) +
+ intel_crtc->dspaddr_offset);
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
} else {
@@ -3005,32 +3147,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
}
}
-u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
- struct drm_i915_gem_object *obj,
- unsigned int plane)
+u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
+ unsigned int rotation)
{
+ struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct i915_ggtt_view view;
- struct i915_vma *vma;
- u64 offset;
-
- intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
- intel_plane->base.state->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 = vma->node.start;
-
- if (plane == 1) {
- offset += vma->ggtt_view.params.rotated.uv_start_page *
- PAGE_SIZE;
- }
-
- WARN_ON(upper_32_bits(offset));
+ intel_fill_fb_ggtt_view(&view, fb, rotation);
- return lower_32_bits(offset);
+ return i915_gem_obj_ggtt_offset_view(obj, &view);
}
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3149,12 +3274,9 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
struct drm_framebuffer *fb = plane_state->base.fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int pipe = intel_crtc->pipe;
u32 plane_ctl, stride_div, stride;
- u32 tile_height, plane_offset, plane_size;
unsigned int rotation = plane_state->base.rotation;
- int x_offset, y_offset;
u32 surf_addr;
int scaler_id = plane_state->scaler_id;
int src_x = plane_state->src.x1 >> 16;
@@ -3175,36 +3297,49 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
plane_ctl |= skl_plane_ctl_rotation(rotation);
- 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);
-
if (intel_rotation_90_or_270(rotation)) {
+ struct drm_rect r = {
+ .x1 = src_x,
+ .x2 = src_x + src_w,
+ .y1 = src_y,
+ .y2 = src_y + src_h,
+ };
int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+ /* Rotate src coordinates to match rotated GTT view */
+ drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
- /* stride = Surface height in tiles */
- tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
- stride = DIV_ROUND_UP(fb->height, tile_height);
- x_offset = stride * tile_height - src_y - src_h;
- y_offset = src_x;
- plane_size = (src_w - 1) << 16 | (src_h - 1);
+ src_x = r.x1;
+ src_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], cpp);
+ stride = intel_fb->rotated[0].pitch;
} else {
- stride = fb->pitches[0] / stride_div;
- x_offset = src_x;
- y_offset = src_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(&src_x, &src_y, fb, 0, rotation);
+ surf_addr = intel_compute_tile_offset(&src_x, &src_y, fb, 0,
+ stride, rotation);
+
+ /* Sizes are 0 based */
+ src_w--;
+ src_h--;
+ dst_w--;
+ dst_h--;
+
+ intel_crtc->adjusted_x = src_x;
+ intel_crtc->adjusted_y = src_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), (src_y << 16) | src_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;
@@ -3221,7 +3356,8 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
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_fb_gtt_offset(fb, rotation) + surf_addr);
POSTING_READ(PLANE_SURF(pipe, 0));
}
@@ -11400,7 +11536,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
const enum pipe pipe = intel_crtc->pipe;
- u32 ctl, stride, tile_height;
+ u32 ctl, stride;
ctl = I915_READ(PLANE_CTL(pipe, 0));
ctl &= ~PLANE_CTL_TILED_MASK;
@@ -11425,9 +11561,11 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
* linear buffers or in number of tiles for tiled buffers.
*/
if (intel_rotation_90_or_270(rotation)) {
- /* stride = Surface height in tiles */
- tile_height = intel_tile_height(dev_priv, fb->modifier[0], 0);
- stride = DIV_ROUND_UP(fb->height, tile_height);
+ int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+ stride = intel_fb->rotated[0].pitch /
+ intel_tile_height(dev_priv, fb->modifier[0], cpp);
} else {
stride = fb->pitches[0] /
intel_fb_stride_alignment(dev_priv, fb->modifier[0],
@@ -11753,8 +11891,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_fb_gtt_offset(fb, primary->state->rotation);
work->gtt_offset += intel_crtc->dspaddr_offset;
if (mmio_flip) {
@@ -14759,7 +14896,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;
@@ -14884,17 +15020,12 @@ static int intel_framebuffer_init(struct drm_device *dev,
if (mode_cmd->offsets[0] != 0)
return -EINVAL;
- 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;
- intel_fill_fb_info(dev_priv, &intel_fb->base);
+ 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) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 674afa1f9f97..84a2a3f109bb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -119,6 +119,16 @@ struct intel_framebuffer {
struct drm_framebuffer base;
struct drm_i915_gem_object *obj;
struct intel_rotation_info rot_info;
+
+ /* for each plane in the normal GTT view */
+ struct {
+ unsigned int x, y;
+ } normal[2];
+ /* for each plane in the rotated GTT view */
+ struct {
+ unsigned int x, y;
+ unsigned int pitch; /* pixels */
+ } rotated[2];
};
struct intel_fbdev {
@@ -1061,6 +1071,11 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
/* intel_display.c */
extern const struct drm_plane_funcs intel_plane_funcs;
+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);
unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
bool intel_has_pending_fb_unpin(struct drm_device *dev);
int intel_pch_rawclk(struct drm_device *dev);
@@ -1217,9 +1232,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
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);
-u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
- struct drm_i915_gem_object *obj,
- unsigned int plane);
+u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, 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 8821533561b1..86176304155d 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -186,15 +186,13 @@ skl_update_plane(struct drm_plane *drm_plane,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(drm_plane);
struct drm_framebuffer *fb = plane_state->base.fb;
- 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;
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
u32 surf_addr;
- u32 tile_height, plane_offset, plane_size;
unsigned int rotation = plane_state->base.rotation;
- int x_offset, y_offset;
int crtc_x = plane_state->dst.x1;
int crtc_y = plane_state->dst.y1;
uint32_t crtc_w = drm_rect_width(&plane_state->dst);
@@ -215,15 +213,6 @@ skl_update_plane(struct drm_plane *drm_plane,
plane_ctl |= skl_plane_ctl_rotation(rotation);
- stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
- fb->pixel_format);
-
- /* 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);
@@ -235,28 +224,44 @@ skl_update_plane(struct drm_plane *drm_plane,
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)) {
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-
- /* stride: Surface height in tiles */
- tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
- 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,
+ };
+ unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+
+ /* 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], cpp);
+ stride = intel_fb->rotated[0].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_tile_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 (plane_state->scaler_id >= 0) {
@@ -278,7 +283,8 @@ skl_update_plane(struct drm_plane *drm_plane,
}
I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
- I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
+ I915_WRITE(PLANE_SURF(pipe, plane),
+ intel_fb_gtt_offset(fb, rotation) + surf_addr);
POSTING_READ(PLANE_SURF(pipe, plane));
}
@@ -351,7 +357,6 @@ vlv_update_plane(struct drm_plane *dplane,
u32 sprctl;
u32 sprsurf_offset, linear_offset;
unsigned int rotation = dplane->state->rotation;
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
int crtc_x = plane_state->dst.x1;
int crtc_y = plane_state->dst.y1;
@@ -422,19 +427,19 @@ vlv_update_plane(struct drm_plane *dplane,
crtc_w--;
crtc_h--;
- linear_offset = y * fb->pitches[0] + x * cpp;
+ intel_add_fb_offsets(&x, &y, fb, 0, rotation);
sprsurf_offset = intel_compute_tile_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 * cpp;
}
+ 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);
@@ -459,8 +464,8 @@ vlv_update_plane(struct drm_plane *dplane,
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_fb_gtt_offset(fb, rotation) + sprsurf_offset);
POSTING_READ(SPSURF(pipe, plane));
}
@@ -493,7 +498,6 @@ ivb_update_plane(struct drm_plane *plane,
u32 sprctl, sprscale = 0;
u32 sprsurf_offset, linear_offset;
unsigned int rotation = plane_state->base.rotation;
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
int crtc_x = plane_state->dst.x1;
int crtc_y = plane_state->dst.y1;
@@ -555,10 +559,9 @@ ivb_update_plane(struct drm_plane *plane,
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 * cpp;
+ intel_add_fb_offsets(&x, &y, fb, 0, rotation);
sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
fb->pitches[0], rotation);
- linear_offset -= sprsurf_offset;
if (rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SPRITE_ROTATE_180;
@@ -567,10 +570,11 @@ ivb_update_plane(struct drm_plane *plane,
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
x += src_w;
y += src_h;
- linear_offset += src_h * fb->pitches[0] + src_w * cpp;
}
}
+ 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);
@@ -599,7 +603,7 @@ ivb_update_plane(struct drm_plane *plane,
I915_WRITE(SPRSCALE(pipe), sprscale);
I915_WRITE(SPRCTL(pipe), sprctl);
I915_WRITE(SPRSURF(pipe),
- i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
+ intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
POSTING_READ(SPRSURF(pipe));
}
@@ -634,7 +638,6 @@ ilk_update_plane(struct drm_plane *plane,
u32 dvscntr, dvsscale;
u32 dvssurf_offset, linear_offset;
unsigned int rotation = plane_state->base.rotation;
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
int crtc_x = plane_state->dst.x1;
int crtc_y = plane_state->dst.y1;
@@ -692,19 +695,19 @@ ilk_update_plane(struct drm_plane *plane,
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 * cpp;
+ intel_add_fb_offsets(&x, &y, fb, 0, rotation);
dvssurf_offset = intel_compute_tile_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 * cpp;
}
+ 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);
@@ -728,7 +731,7 @@ ilk_update_plane(struct drm_plane *plane,
I915_WRITE(DVSSCALE(pipe), dvsscale);
I915_WRITE(DVSCNTR(pipe), dvscntr);
I915_WRITE(DVSSURF(pipe),
- i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
+ intel_fb_gtt_offset(fb, rotation) + dvssurf_offset);
POSTING_READ(DVSSURF(pipe));
}
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v3 11/21] drm/i915: Don't pass pitch to intel_compute_page_offset()
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (9 preceding siblings ...)
2016-02-15 20:54 ` [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 12/21] drm/i915: Move SKL hw stride calculation into a helper ville.syrjala
` (10 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 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.
This leaves 'stride_div' in the skl plane update hooks as a mostly useless
variable so just get rid of it.
v2: Add a note why stride_div got nuked
v3: Extract intel_fb_pitch() since it can be useful later
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
---
drivers/gpu/drm/i915/intel_display.c | 34 ++++++++++++++++++++--------------
drivers/gpu/drm/i915/intel_drv.h | 1 -
drivers/gpu/drm/i915/intel_sprite.c | 26 +++++++++++---------------
3 files changed, 31 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index acd92f957054..1561923906a1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2437,6 +2437,15 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation
i915_gem_object_unpin_from_display_plane(obj, &view);
}
+static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
+ unsigned int rotation)
+{
+ if (intel_rotation_90_or_270(rotation))
+ return to_intel_framebuffer(fb)->rotated[plane].pitch;
+ else
+ return fb->pitches[plane];
+}
+
/*
* Convert the x/y offsets into a linear offset.
* Only valid with 0/180 degree rotation, which is fine since linear
@@ -2570,11 +2579,11 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
u32 intel_compute_tile_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);
u32 alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
+ int pitch = intel_fb_pitch(fb, plane, rotation);
return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
rotation, alignment);
@@ -3000,8 +3009,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
if (INTEL_INFO(dev)->gen >= 4)
intel_crtc->dspaddr_offset =
- intel_compute_tile_offset(&x, &y, fb, 0,
- fb->pitches[0], rotation);
+ intel_compute_tile_offset(&x, &y, fb, 0, rotation);
if (rotation == BIT(DRM_ROTATE_180)) {
dspcntr |= DISPPLANE_ROTATE_180;
@@ -3103,8 +3111,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
intel_add_fb_offsets(&x, &y, fb, 0, rotation);
intel_crtc->dspaddr_offset =
- intel_compute_tile_offset(&x, &y, fb, 0,
- fb->pitches[0], rotation);
+ intel_compute_tile_offset(&x, &y, fb, 0, rotation);
if (rotation == BIT(DRM_ROTATE_180)) {
dspcntr |= DISPPLANE_ROTATE_180;
@@ -3275,7 +3282,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
struct drm_framebuffer *fb = plane_state->base.fb;
int pipe = intel_crtc->pipe;
- u32 plane_ctl, stride_div, stride;
+ u32 plane_ctl, stride;
unsigned int rotation = plane_state->base.rotation;
u32 surf_addr;
int scaler_id = plane_state->scaler_id;
@@ -3315,17 +3322,16 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
src_w = drm_rect_width(&r);
src_h = drm_rect_height(&r);
- stride_div = intel_tile_height(dev_priv, fb->modifier[0], cpp);
- stride = intel_fb->rotated[0].pitch;
+ stride = intel_fb->rotated[0].pitch /
+ intel_tile_height(dev_priv, fb->modifier[0], cpp);
} 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(&src_x, &src_y, fb, 0, rotation);
- surf_addr = intel_compute_tile_offset(&src_x, &src_y, fb, 0,
- stride, rotation);
+ surf_addr = intel_compute_tile_offset(&src_x, &src_y, fb, 0, rotation);
/* Sizes are 0 based */
src_w--;
@@ -3338,7 +3344,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_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 84a2a3f109bb..40cbe5c6163c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1191,7 +1191,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)
u32 intel_compute_tile_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 86176304155d..31be24f27207 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -189,7 +189,7 @@ skl_update_plane(struct drm_plane *drm_plane,
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;
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
u32 surf_addr;
unsigned int rotation = plane_state->base.rotation;
@@ -241,17 +241,16 @@ skl_update_plane(struct drm_plane *drm_plane,
src_w = drm_rect_width(&r);
src_h = drm_rect_height(&r);
- stride_div = intel_tile_height(dev_priv, fb->modifier[0], cpp);
- stride = intel_fb->rotated[0].pitch;
+ stride = intel_fb->rotated[0].pitch /
+ intel_tile_height(dev_priv, fb->modifier[0], cpp);
} 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_tile_offset(&x, &y, fb, 0,
- stride, rotation);
+ surf_addr = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
/* Sizes are 0 based */
src_w--;
@@ -260,7 +259,7 @@ skl_update_plane(struct drm_plane *drm_plane,
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 */
@@ -428,8 +427,7 @@ vlv_update_plane(struct drm_plane *dplane,
crtc_h--;
intel_add_fb_offsets(&x, &y, fb, 0, rotation);
- sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
- fb->pitches[0], rotation);
+ sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
if (rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SP_ROTATE_180;
@@ -560,8 +558,7 @@ ivb_update_plane(struct drm_plane *plane,
sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
intel_add_fb_offsets(&x, &y, fb, 0, rotation);
- sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
- fb->pitches[0], rotation);
+ sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
if (rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SPRITE_ROTATE_180;
@@ -696,8 +693,7 @@ ilk_update_plane(struct drm_plane *plane,
dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
intel_add_fb_offsets(&x, &y, fb, 0, rotation);
- dvssurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
- fb->pitches[0], rotation);
+ dvssurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
if (rotation == BIT(DRM_ROTATE_180)) {
dvscntr |= DVS_ROTATE_180;
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 12/21] drm/i915: Move SKL hw stride calculation into a helper
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (10 preceding siblings ...)
2016-02-15 20:54 ` [PATCH v3 11/21] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 13/21] drm/i915: Pass around plane_state instead of fb+rotation ville.syrjala
` (9 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
We repeat the SKL stride register value calculations a several places.
Move it into a small helper function.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 52 +++++++++++++++++-------------------
drivers/gpu/drm/i915/intel_drv.h | 2 ++
drivers/gpu/drm/i915/intel_sprite.c | 12 ++-------
3 files changed, 29 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1561923906a1..66794681b2ba 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3192,6 +3192,28 @@ static void skl_detach_scalers(struct intel_crtc *intel_crtc)
}
}
+u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane,
+ unsigned int rotation)
+{
+ const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+ u32 stride = intel_fb_pitch(fb, plane, rotation);
+
+ /*
+ * The stride is either expressed as a multiple of 64 bytes chunks for
+ * linear buffers or in number of tiles for tiled buffers.
+ */
+ if (intel_rotation_90_or_270(rotation)) {
+ int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+
+ stride /= intel_tile_height(dev_priv, fb->modifier[0], cpp);
+ } else {
+ stride /= intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+ fb->pixel_format);
+ }
+
+ return stride;
+}
+
u32 skl_plane_ctl_format(uint32_t pixel_format)
{
switch (pixel_format) {
@@ -3282,8 +3304,9 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
struct drm_framebuffer *fb = plane_state->base.fb;
int pipe = intel_crtc->pipe;
- u32 plane_ctl, stride;
+ u32 plane_ctl;
unsigned int rotation = plane_state->base.rotation;
+ u32 stride = skl_plane_stride(fb, 0, rotation);
u32 surf_addr;
int scaler_id = plane_state->scaler_id;
int src_x = plane_state->src.x1 >> 16;
@@ -3311,8 +3334,6 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
.y1 = src_y,
.y2 = src_y + src_h,
};
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
/* Rotate src coordinates to match rotated GTT view */
drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
@@ -3321,13 +3342,6 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
src_y = r.y1;
src_w = drm_rect_width(&r);
src_h = drm_rect_height(&r);
-
- stride = intel_fb->rotated[0].pitch /
- intel_tile_height(dev_priv, fb->modifier[0], cpp);
- } else {
- stride = fb->pitches[0] /
- intel_fb_stride_alignment(dev_priv, fb->modifier[0],
- fb->pixel_format);
}
intel_add_fb_offsets(&src_x, &src_y, fb, 0, rotation);
@@ -11542,7 +11556,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
const enum pipe pipe = intel_crtc->pipe;
- u32 ctl, stride;
+ u32 ctl, stride = skl_plane_stride(fb, 0, rotation);
ctl = I915_READ(PLANE_CTL(pipe, 0));
ctl &= ~PLANE_CTL_TILED_MASK;
@@ -11563,22 +11577,6 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
}
/*
- * The stride is either expressed as a multiple of 64 bytes chunks for
- * linear buffers or in number of tiles for tiled buffers.
- */
- if (intel_rotation_90_or_270(rotation)) {
- int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-
- stride = intel_fb->rotated[0].pitch /
- intel_tile_height(dev_priv, fb->modifier[0], cpp);
- } else {
- stride = fb->pitches[0] /
- intel_fb_stride_alignment(dev_priv, fb->modifier[0],
- fb->pixel_format);
- }
-
- /*
* Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
* PLANE_SURF updates, the update is then guaranteed to be atomic.
*/
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 40cbe5c6163c..a32470acf529 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1236,6 +1236,8 @@ u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, unsigned int rotation);
u32 skl_plane_ctl_format(uint32_t pixel_format);
u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
u32 skl_plane_ctl_rotation(unsigned int rotation);
+u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane,
+ unsigned int rotation);
/* intel_csr.c */
void intel_csr_ucode_init(struct drm_i915_private *);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 31be24f27207..94dd27045b51 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -186,13 +186,13 @@ skl_update_plane(struct drm_plane *drm_plane,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(drm_plane);
struct drm_framebuffer *fb = plane_state->base.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;
+ u32 plane_ctl;
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
u32 surf_addr;
unsigned int rotation = plane_state->base.rotation;
+ u32 stride = skl_plane_stride(fb, 0, rotation);
int crtc_x = plane_state->dst.x1;
int crtc_y = plane_state->dst.y1;
uint32_t crtc_w = drm_rect_width(&plane_state->dst);
@@ -231,7 +231,6 @@ skl_update_plane(struct drm_plane *drm_plane,
.y1 = y,
.y2 = y + src_h,
};
- unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
/* Rotate src coordinates to match rotated GTT view */
drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
@@ -240,13 +239,6 @@ skl_update_plane(struct drm_plane *drm_plane,
y = r.y1;
src_w = drm_rect_width(&r);
src_h = drm_rect_height(&r);
-
- stride = intel_fb->rotated[0].pitch /
- intel_tile_height(dev_priv, fb->modifier[0], cpp);
- } else {
- 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);
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 13/21] drm/i915: Pass around plane_state instead of fb+rotation
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (11 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 12/21] drm/i915: Move SKL hw stride calculation into a helper ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 14/21] drm/i915: Use fb modifiers for display tiling decisions ville.syrjala
` (8 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
intel_compute_tile_offset() and intel_add_fb_offsets() get passed the fb
and the rotation. As both of those come from the plane state we can just
pass that in instead.
For extra consitency pass the plane state to intel_fb_xy_to_linear() as
well even though it only really needs the fb.
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 | 35 ++++++++++++++++++++---------------
drivers/gpu/drm/i915/intel_drv.h | 9 ++++-----
drivers/gpu/drm/i915/intel_sprite.c | 22 +++++++++++-----------
3 files changed, 35 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 66794681b2ba..5f60fe0214e1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2453,8 +2453,10 @@ static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
* with gen2/3, and 90/270 degree rotations isn't supported on any of them.
*/
u32 intel_fb_xy_to_linear(int x, int y,
- const struct drm_framebuffer *fb, int plane)
+ const struct intel_plane_state *state,
+ int plane)
{
+ const struct drm_framebuffer *fb = state->base.fb;
unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
unsigned int pitch = fb->pitches[plane];
@@ -2467,11 +2469,12 @@ u32 intel_fb_xy_to_linear(int x, int y,
* 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 intel_plane_state *state,
+ int plane)
{
- const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+ const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb);
+ unsigned int rotation = state->base.rotation;
if (intel_rotation_90_or_270(rotation)) {
*x += intel_fb->rotated[plane].x;
@@ -2578,10 +2581,12 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
}
u32 intel_compute_tile_offset(int *x, int *y,
- const struct drm_framebuffer *fb, int plane,
- unsigned int rotation)
+ const struct intel_plane_state *state,
+ int plane)
{
- const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+ const struct drm_i915_private *dev_priv = to_i915(state->base.plane->dev);
+ const struct drm_framebuffer *fb = state->base.fb;
+ unsigned int rotation = state->base.rotation;
u32 alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
int pitch = intel_fb_pitch(fb, plane, rotation);
@@ -3005,11 +3010,11 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
if (IS_G4X(dev))
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
- intel_add_fb_offsets(&x, &y, fb, 0, rotation);
+ intel_add_fb_offsets(&x, &y, plane_state, 0);
if (INTEL_INFO(dev)->gen >= 4)
intel_crtc->dspaddr_offset =
- intel_compute_tile_offset(&x, &y, fb, 0, rotation);
+ intel_compute_tile_offset(&x, &y, plane_state, 0);
if (rotation == BIT(DRM_ROTATE_180)) {
dspcntr |= DISPPLANE_ROTATE_180;
@@ -3018,7 +3023,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
y += (crtc_state->pipe_src_h - 1);
}
- linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+ linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
if (INTEL_INFO(dev)->gen < 4)
intel_crtc->dspaddr_offset = linear_offset;
@@ -3108,10 +3113,10 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
- intel_add_fb_offsets(&x, &y, fb, 0, rotation);
+ intel_add_fb_offsets(&x, &y, plane_state, 0);
intel_crtc->dspaddr_offset =
- intel_compute_tile_offset(&x, &y, fb, 0, rotation);
+ intel_compute_tile_offset(&x, &y, plane_state, 0);
if (rotation == BIT(DRM_ROTATE_180)) {
dspcntr |= DISPPLANE_ROTATE_180;
@@ -3122,7 +3127,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
}
}
- linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+ linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
intel_crtc->adjusted_x = x;
intel_crtc->adjusted_y = y;
@@ -3344,8 +3349,8 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
src_h = drm_rect_height(&r);
}
- intel_add_fb_offsets(&src_x, &src_y, fb, 0, rotation);
- surf_addr = intel_compute_tile_offset(&src_x, &src_y, fb, 0, rotation);
+ intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
+ surf_addr = intel_compute_tile_offset(&src_x, &src_y, plane_state, 0);
/* Sizes are 0 based */
src_w--;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a32470acf529..0c5e90f3b405 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1072,10 +1072,10 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
/* intel_display.c */
extern const struct drm_plane_funcs intel_plane_funcs;
unsigned int intel_fb_xy_to_linear(int x, int y,
- const struct drm_framebuffer *fb, int plane);
+ const struct intel_plane_state *state,
+ int plane);
void intel_add_fb_offsets(int *x, int *y,
- const struct drm_framebuffer *fb, int plane,
- unsigned int rotation);
+ const struct intel_plane_state *state, int plane);
unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
bool intel_has_pending_fb_unpin(struct drm_device *dev);
int intel_pch_rawclk(struct drm_device *dev);
@@ -1190,8 +1190,7 @@ 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)
u32 intel_compute_tile_offset(int *x, int *y,
- const struct drm_framebuffer *fb, int plane,
- unsigned int rotation);
+ const struct intel_plane_state *state, int plane);
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 94dd27045b51..d1211df1d373 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,
src_h = drm_rect_height(&r);
}
- intel_add_fb_offsets(&x, &y, fb, 0, rotation);
- surf_addr = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
+ intel_add_fb_offsets(&x, &y, plane_state, 0);
+ surf_addr = intel_compute_tile_offset(&x, &y, plane_state, 0);
/* Sizes are 0 based */
src_w--;
@@ -418,8 +418,8 @@ vlv_update_plane(struct drm_plane *dplane,
crtc_w--;
crtc_h--;
- intel_add_fb_offsets(&x, &y, fb, 0, rotation);
- sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
+ intel_add_fb_offsets(&x, &y, plane_state, 0);
+ sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
if (rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SP_ROTATE_180;
@@ -428,7 +428,7 @@ vlv_update_plane(struct drm_plane *dplane,
y += src_h;
}
- linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+ linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
if (key->flags) {
I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
@@ -549,8 +549,8 @@ ivb_update_plane(struct drm_plane *plane,
if (crtc_w != src_w || crtc_h != src_h)
sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
- intel_add_fb_offsets(&x, &y, fb, 0, rotation);
- sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
+ intel_add_fb_offsets(&x, &y, plane_state, 0);
+ sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
if (rotation == BIT(DRM_ROTATE_180)) {
sprctl |= SPRITE_ROTATE_180;
@@ -562,7 +562,7 @@ ivb_update_plane(struct drm_plane *plane,
}
}
- linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+ linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
if (key->flags) {
I915_WRITE(SPRKEYVAL(pipe), key->min_value);
@@ -684,8 +684,8 @@ ilk_update_plane(struct drm_plane *plane,
if (crtc_w != src_w || crtc_h != src_h)
dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
- intel_add_fb_offsets(&x, &y, fb, 0, rotation);
- dvssurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, rotation);
+ intel_add_fb_offsets(&x, &y, plane_state, 0);
+ dvssurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
if (rotation == BIT(DRM_ROTATE_180)) {
dvscntr |= DVS_ROTATE_180;
@@ -694,7 +694,7 @@ ilk_update_plane(struct drm_plane *plane,
y += src_h;
}
- linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
+ linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
if (key->flags) {
I915_WRITE(DVSKEYVAL(pipe), key->min_value);
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 14/21] drm/i915: Use fb modifiers for display tiling decisions
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (12 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 13/21] drm/i915: Pass around plane_state instead of fb+rotation ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-03-17 8:15 ` Matthew Auld
2016-02-15 20:54 ` [PATCH 15/21] drm/i915: Adjust obj tiling vs. fb modifier rules ville.syrjala
` (7 subsequent siblings)
21 siblings, 1 reply; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Soon the fence tiling mode may not always match the fb modifier
even for X tiled buffers. So let's use the fb modifier
consistently for all display tiling decisions.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 33 ++++++++++++++++++++++-----------
drivers/gpu/drm/i915/intel_sprite.c | 15 ++++++---------
2 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5f60fe0214e1..733bd68d2e01 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2606,6 +2606,18 @@ static void intel_fb_offset_to_xy(int *x, int *y,
*x = linear_offset % pitch / cpp;
}
+static unsigned int intel_fb_modifier_to_tiling(uint64_t fb_modifier)
+{
+ switch (fb_modifier) {
+ case I915_FORMAT_MOD_X_TILED:
+ return I915_TILING_X;
+ case I915_FORMAT_MOD_Y_TILED:
+ return I915_TILING_Y;
+ default:
+ return I915_TILING_NONE;
+ }
+}
+
static int
intel_fill_fb_info(struct drm_i915_private *dev_priv,
struct drm_framebuffer *fb)
@@ -3004,7 +3016,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
}
if (INTEL_INFO(dev)->gen >= 4 &&
- obj->tiling_mode != I915_TILING_NONE)
+ fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISPPLANE_TILED;
if (IS_G4X(dev))
@@ -3069,7 +3081,6 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
struct drm_framebuffer *fb = plane_state->base.fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int plane = intel_crtc->plane;
u32 linear_offset;
u32 dspcntr;
@@ -3107,7 +3118,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
BUG();
}
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISPPLANE_TILED;
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
@@ -11377,7 +11388,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
intel_ring_emit(ring, fb->pitches[0]);
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset |
- obj->tiling_mode);
+ intel_fb_modifier_to_tiling(fb->modifier[0]));
/* XXX Enabling the panel-fitter across page-flip is so far
* untested on non-native modes, so ignore it for now.
@@ -11410,7 +11421,8 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, MI_DISPLAY_FLIP |
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
- intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
+ intel_ring_emit(ring, fb->pitches[0] |
+ intel_fb_modifier_to_tiling(fb->modifier[0]));
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
/* Contrary to the suggestions in the documentation,
@@ -11514,7 +11526,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
}
intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
- intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
+ intel_ring_emit(ring, fb->pitches[0] |
+ intel_fb_modifier_to_tiling(fb->modifier[0]));
intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
intel_ring_emit(ring, (MI_NOOP));
@@ -11597,15 +11610,13 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_framebuffer *intel_fb =
- to_intel_framebuffer(intel_crtc->base.primary->fb);
- struct drm_i915_gem_object *obj = intel_fb->obj;
+ struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
i915_reg_t reg = DSPCNTR(intel_crtc->plane);
u32 dspcntr;
dspcntr = I915_READ(reg);
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISPPLANE_TILED;
else
dspcntr &= ~DISPPLANE_TILED;
@@ -11870,7 +11881,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
ring = &dev_priv->ring[BCS];
- if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
+ if (fb->modifier[0] != old_fb->modifier[0])
/* vlv: DISPLAY_FLIP fails to change tiling */
ring = NULL;
} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index d1211df1d373..899dbb4d78a8 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -342,7 +342,6 @@ vlv_update_plane(struct drm_plane *dplane,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(dplane);
struct drm_framebuffer *fb = plane_state->base.fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int pipe = intel_plane->pipe;
int plane = intel_plane->plane;
u32 sprctl;
@@ -409,7 +408,7 @@ vlv_update_plane(struct drm_plane *dplane,
*/
sprctl |= SP_GAMMA_ENABLE;
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
sprctl |= SP_TILED;
/* Sizes are 0 based */
@@ -445,7 +444,7 @@ vlv_update_plane(struct drm_plane *dplane,
I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
else
I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
@@ -483,7 +482,6 @@ ivb_update_plane(struct drm_plane *plane,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
struct drm_framebuffer *fb = plane_state->base.fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
enum pipe pipe = intel_plane->pipe;
u32 sprctl, sprscale = 0;
u32 sprsurf_offset, linear_offset;
@@ -529,7 +527,7 @@ ivb_update_plane(struct drm_plane *plane,
*/
sprctl |= SPRITE_GAMMA_ENABLE;
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
sprctl |= SPRITE_TILED;
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
@@ -582,7 +580,7 @@ ivb_update_plane(struct drm_plane *plane,
* register */
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
- else if (obj->tiling_mode != I915_TILING_NONE)
+ else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
else
I915_WRITE(SPRLINOFF(pipe), linear_offset);
@@ -622,7 +620,6 @@ ilk_update_plane(struct drm_plane *plane,
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_plane *intel_plane = to_intel_plane(plane);
struct drm_framebuffer *fb = plane_state->base.fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
int pipe = intel_plane->pipe;
u32 dvscntr, dvsscale;
u32 dvssurf_offset, linear_offset;
@@ -668,7 +665,7 @@ ilk_update_plane(struct drm_plane *plane,
*/
dvscntr |= DVS_GAMMA_ENABLE;
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
dvscntr |= DVS_TILED;
if (IS_GEN6(dev))
@@ -710,7 +707,7 @@ ilk_update_plane(struct drm_plane *plane,
I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
- if (obj->tiling_mode != I915_TILING_NONE)
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
else
I915_WRITE(DVSLINOFF(pipe), linear_offset);
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 15/21] drm/i915: Adjust obj tiling vs. fb modifier rules
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (13 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 14/21] drm/i915: Use fb modifiers for display tiling decisions ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-03-17 8:08 ` Matthew Auld
2016-02-15 20:54 ` [PATCH 16/21] drm/i915: Limit fb x offset due to fences ville.syrjala
` (6 subsequent siblings)
21 siblings, 1 reply; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Currently we requite the object to be X tiled if the fb is X
tiled. The argument is supposedly FBC GTT tracking. But
actually that no longer holds water since FBC supports
Y tiling as well on SKL+.
A better rule IMO is to require that if there is a fence, the
fb modifier match the object tiling mode. But if the object is linear,
we can allow the fb modifier to be anything. The idea being that
if the user set the tiling mode on the object, presumaly the intention
is to actually use the fence for CPU access. But if the tiling mode is
not set, the user has no intention of using a fence (and can't actually
since we disalling tiling mode changes when there are framebuffers
associated with the object).
On gen2/3 we must keep to the rule that the object and fb
must be either both linear or both X tiled. No mixing allowed
since the display engine itself will use the fence if it's present.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 733bd68d2e01..de312af9b117 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14922,17 +14922,19 @@ static int intel_framebuffer_init(struct drm_device *dev,
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
- /* Enforce that fb modifier and tiling mode match, but only for
- * X-tiled. This is needed for FBC. */
- if (!!(obj->tiling_mode == I915_TILING_X) !=
- !!(mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)) {
+ /*
+ * If there's a fence, enforce that
+ * the fb modifier and tiling mode match.
+ */
+ if (obj->tiling_mode != I915_TILING_NONE &&
+ obj->tiling_mode != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
DRM_DEBUG("tiling_mode doesn't match fb modifier\n");
return -EINVAL;
}
} else {
- if (obj->tiling_mode == I915_TILING_X)
+ if (obj->tiling_mode == I915_TILING_X) {
mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
- else if (obj->tiling_mode == I915_TILING_Y) {
+ } else if (obj->tiling_mode == I915_TILING_Y) {
DRM_DEBUG("No Y tiling for legacy addfb\n");
return -EINVAL;
}
@@ -14956,6 +14958,16 @@ static int intel_framebuffer_init(struct drm_device *dev,
return -EINVAL;
}
+ /*
+ * gen2/3 display engine uses the fence if present,
+ * so the tiling mode must match the fb modifier exactly.
+ */
+ if (INTEL_INFO(dev_priv)->gen < 4 &&
+ obj->tiling_mode != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
+ DRM_DEBUG("tiling_mode must match fb modifier exactly on gen2/3\n");
+ return -EINVAL;
+ }
+
stride_alignment = intel_fb_stride_alignment(dev_priv,
mode_cmd->modifier[0],
mode_cmd->pixel_format);
@@ -14975,7 +14987,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
return -EINVAL;
}
- if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED &&
+ if (obj->tiling_mode != I915_TILING_NONE &&
mode_cmd->pitches[0] != obj->stride) {
DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
mode_cmd->pitches[0], obj->stride);
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 16/21] drm/i915: Limit fb x offset due to fences
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (14 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 15/21] drm/i915: Adjust obj tiling vs. fb modifier rules ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 17/21] drm/i915: Allow calling intel_adjust_tile_offset() multiple times ville.syrjala
` (5 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
If there's a fence on the object it will be aligned to the start
of the object, and hence CPU rendering to any fb that straddles
the fence edge will come out wrong due to lines wrapping at the
wrong place.
We have no API to manage fences on a sub-object level, so we can't
really fix this in any way. Additonally gen2/3 fences are rather
coarse grained so adjusting the offset migth not even be possible.
Avoid these problems by requiring the fb layout to agree with the
fence layout (if present).
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index de312af9b117..f805ec332393 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2643,6 +2643,22 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
intel_fb_offset_to_xy(&x, &y, fb, i);
/*
+ * The fence (if used) is aligned to the start of the object
+ * so having the framebuffer wrap around across the edge of the
+ * fenced region doesn't really work. We have no API to configure
+ * the fence start offset within the object (nor could we probably
+ * on gen2/3). So it's just easier if we just require that the
+ * fb layout agrees with the fence layout. We already check that the
+ * fb stride matches the fence stride elsewhere.
+ */
+ if (intel_fb->obj->tiling_mode != I915_TILING_NONE &&
+ (x + width) * cpp > fb->pitches[i]) {
+ DRM_DEBUG("bad fb plane %d offset: 0x%x\n",
+ i, fb->offsets[i]);
+ return -EINVAL;
+ }
+
+ /*
* First pixel of the framebuffer from
* the start of the normal gtt mapping.
*/
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 17/21] drm/i915: Allow calling intel_adjust_tile_offset() multiple times
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (15 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 16/21] drm/i915: Limit fb x offset due to fences ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 18/21] drm/i915: Make intel_adjust_tile_offset() work for linear buffers ville.syrjala
` (4 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
Minimize the resulting X coordinate after intel_adjust_tile_offset() is
done with it's offset adjustment. This allows calling
intel_adjust_tile_offset() multiple times in case we need to adjust
the offset several times.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f805ec332393..79dcb7d26b7a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2500,6 +2500,7 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
u32 old_offset,
u32 new_offset)
{
+ unsigned int pitch_pixels = pitch_tiles * tile_width;
unsigned int tiles;
WARN_ON(old_offset & (tile_size - 1));
@@ -2511,6 +2512,10 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
*y += tiles / pitch_tiles * tile_height;
*x += tiles % pitch_tiles * tile_width;
+ /* minimize x in case it got needlessly big */
+ *y += *x / pitch_pixels * tile_height;
+ *x %= pitch_pixels;
+
return new_offset;
}
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 18/21] drm/i915: Make intel_adjust_tile_offset() work for linear buffers
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (16 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 17/21] drm/i915: Allow calling intel_adjust_tile_offset() multiple times ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 19/21] drm/i915: Compute display surface offset in the plane check hook for SKL+ ville.syrjala
` (3 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
To make life less surprising we can make intel_adjust_tile_offset()
deal with linear buffers as well. Currently it doesn't seem like there's
a real need for this since only X tiling and NV12 (which would always
be tiled currently) should need it. But I've used it for some debug
hacks already so seems like a reasonable thing to have.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 73 ++++++++++++++++++++++++++++--------
1 file changed, 57 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 79dcb7d26b7a..0b1f45d7612e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2486,19 +2486,16 @@ void intel_add_fb_offsets(int *x, int *y,
}
/*
- * Adjust the tile offset by moving the difference into
- * the x/y offsets.
- *
* Input tile dimensions and pitch must already be
* rotated to match x and y, and in pixel units.
*/
-static u32 intel_adjust_tile_offset(int *x, int *y,
- unsigned int tile_width,
- unsigned int tile_height,
- unsigned int tile_size,
- unsigned int pitch_tiles,
- u32 old_offset,
- u32 new_offset)
+static u32 _intel_adjust_tile_offset(int *x, int *y,
+ unsigned int tile_width,
+ unsigned int tile_height,
+ unsigned int tile_size,
+ unsigned int pitch_tiles,
+ u32 old_offset,
+ u32 new_offset)
{
unsigned int pitch_pixels = pitch_tiles * tile_width;
unsigned int tiles;
@@ -2520,6 +2517,50 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
}
/*
+ * Adjust the tile offset by moving the difference into
+ * the x/y offsets.
+ */
+static u32 intel_adjust_tile_offset(int *x, int *y,
+ const struct intel_plane_state *state, int plane,
+ u32 old_offset, u32 new_offset)
+{
+ const struct drm_i915_private *dev_priv = to_i915(state->base.plane->dev);
+ const struct drm_framebuffer *fb = state->base.fb;
+ unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+ unsigned int rotation = state->base.rotation;
+ unsigned int pitch = intel_fb_pitch(fb, plane, rotation);
+
+ WARN_ON(new_offset > old_offset);
+
+ if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
+ unsigned int tile_size, tile_width, tile_height;
+ unsigned int pitch_tiles;
+
+ tile_size = intel_tile_size(dev_priv);
+ intel_tile_dims(dev_priv, &tile_width, &tile_height,
+ fb->modifier[plane], cpp);
+
+ if (intel_rotation_90_or_270(rotation)) {
+ pitch_tiles = pitch / tile_height;
+ swap(tile_width, tile_height);
+ } else {
+ pitch_tiles = pitch / (tile_width * cpp);
+ }
+
+ _intel_adjust_tile_offset(x, y, tile_width, tile_height,
+ tile_size, pitch_tiles,
+ old_offset, new_offset);
+ } else {
+ old_offset += *y * pitch + *x * cpp;
+
+ *y = (old_offset - new_offset) / pitch;
+ *x = ((old_offset - new_offset) - *y * pitch) / cpp;
+ }
+
+ return new_offset;
+}
+
+/*
* Computes the linear offset to the base tile and adjusts
* x, y. bytes per pixel is assumed to be a power-of-two.
*
@@ -2571,9 +2612,9 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
offset = (tile_rows * pitch_tiles + tiles) * tile_size;
offset_aligned = offset & ~alignment;
- intel_adjust_tile_offset(x, y, tile_width, tile_height,
- tile_size, pitch_tiles,
- offset, offset_aligned);
+ _intel_adjust_tile_offset(x, y, tile_width, tile_height,
+ tile_size, pitch_tiles,
+ offset, offset_aligned);
} else {
offset = *y * pitch + *x * cpp;
offset_aligned = offset & ~alignment;
@@ -2720,9 +2761,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
* We only keep the x/y offsets, so push all of the
* gtt offset into the x/y offsets.
*/
- intel_adjust_tile_offset(&x, &y, tile_size,
- tile_width, tile_height, pitch_tiles,
- gtt_offset_rotated * tile_size, 0);
+ _intel_adjust_tile_offset(&x, &y, tile_size,
+ tile_width, tile_height, pitch_tiles,
+ gtt_offset_rotated * tile_size, 0);
gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height;
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 19/21] drm/i915: Compute display surface offset in the plane check hook for SKL+
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (17 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 18/21] drm/i915: Make intel_adjust_tile_offset() work for linear buffers ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH 20/21] drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+ ville.syrjala
` (2 subsequent siblings)
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
SKL has nasty limitations with the display surface offsets:
* source x offset + width must be less than the stride for X tiled
surfaces or the display engine falls over
* the surface offset requires lots of alignment (256K or 1M)
These facts mean that we can't just pick any suitably aligned tile
boundary as the offset and expect the resulting x offset to be useable.
The solution is to start with the closest boundary as before, but then
keep searhing backwards until we find one that works, or don't. This
means we must be prepared to fail, hence the whole surface offset
calculation needs to be moved to the .check_plane() hook from the
.update_plane() hook.
While at it we can check that the source width/height don't exceed
maximum plane size limits.
We'll store the results of the computation in the plane state to make
it easy for the .update_plane() hook to do its thing.
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 164 +++++++++++++++++++++++++++++------
drivers/gpu/drm/i915/intel_drv.h | 5 ++
drivers/gpu/drm/i915/intel_sprite.c | 33 +++----
3 files changed, 151 insertions(+), 51 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0b1f45d7612e..ad739f79e710 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3011,6 +3011,120 @@ valid_fb:
obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit;
}
+static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
+ unsigned int rotation)
+{
+ int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+
+ switch (fb->modifier[plane]) {
+ case DRM_FORMAT_MOD_NONE:
+ case I915_FORMAT_MOD_X_TILED:
+ switch (cpp) {
+ case 8:
+ return 4096;
+ case 4:
+ case 2:
+ case 1:
+ return 8192;
+ default:
+ MISSING_CASE(cpp);
+ break;
+ }
+ break;
+ case I915_FORMAT_MOD_Y_TILED:
+ case I915_FORMAT_MOD_Yf_TILED:
+ switch (cpp) {
+ case 8:
+ return 2048;
+ case 4:
+ return 4096;
+ case 2:
+ case 1:
+ return 8192;
+ default:
+ MISSING_CASE(cpp);
+ break;
+ }
+ break;
+ default:
+ MISSING_CASE(fb->modifier[plane]);
+ }
+
+ return 2048;
+}
+
+static int skl_check_main_surface(struct intel_plane_state *plane_state)
+{
+ const struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev);
+ const struct drm_framebuffer *fb = plane_state->base.fb;
+ unsigned int rotation = plane_state->base.rotation;
+ int x = plane_state->src.x1 >> 16;
+ int y = plane_state->src.y1 >> 16;
+ int w = drm_rect_width(&plane_state->src) >> 16;
+ int h = drm_rect_height(&plane_state->src) >> 16;
+ int max_width = skl_max_plane_width(fb, 0, rotation);
+ int max_height = 4096;
+ u32 alignment, offset;
+
+ if (w > max_width || h > max_height) {
+ DRM_DEBUG_KMS("requested Y/RGB source size %dx%d too big (limit %dx%d)\n",
+ w, h, max_width, max_height);
+ return -EINVAL;
+ }
+
+ intel_add_fb_offsets(&x, &y, plane_state, 0);
+ offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
+
+ alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
+
+ /*
+ * When using an X-tiled surface, the plane blows up
+ * if the x offset + width exceed the stride.
+ *
+ * TODO: linear and Y-tiled seem fine, Yf untested,
+ */
+ if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) {
+ int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+
+ for (;;) {
+ if ((x + w) * cpp <= fb->pitches[0])
+ break;
+
+ if (offset == 0) {
+ DRM_DEBUG_KMS("Unable to find suitable display surface offset\n");
+ return -EINVAL;
+ }
+
+ offset = intel_adjust_tile_offset(&x, &y, plane_state, 0,
+ offset, offset - alignment);
+ }
+ }
+
+ plane_state->main.offset = offset;
+ plane_state->main.x = x;
+ plane_state->main.y = y;
+
+ return 0;
+}
+
+int skl_check_plane_surface(struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->base.fb;
+ unsigned int rotation = plane_state->base.rotation;
+ int ret;
+
+ /* Rotate src coordinates to match rotated GTT view */
+ if (intel_rotation_90_or_270(rotation))
+ drm_rect_rotate(&plane_state->src,
+ fb->width, fb->height, BIT(DRM_ROTATE_270));
+
+ ret = skl_check_main_surface(plane_state);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static void i9xx_update_primary_plane(struct drm_plane *primary,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
@@ -3385,10 +3499,10 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
u32 plane_ctl;
unsigned int rotation = plane_state->base.rotation;
u32 stride = skl_plane_stride(fb, 0, rotation);
- u32 surf_addr;
+ u32 surf_addr = plane_state->main.offset;
int scaler_id = plane_state->scaler_id;
- int src_x = plane_state->src.x1 >> 16;
- int src_y = plane_state->src.y1 >> 16;
+ int src_x = plane_state->main.x;
+ int src_y = plane_state->main.y;
int src_w = drm_rect_width(&plane_state->src) >> 16;
int src_h = drm_rect_height(&plane_state->src) >> 16;
int dst_x = plane_state->dst.x1;
@@ -3405,26 +3519,6 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
plane_ctl |= skl_plane_ctl_rotation(rotation);
- if (intel_rotation_90_or_270(rotation)) {
- struct drm_rect r = {
- .x1 = src_x,
- .x2 = src_x + src_w,
- .y1 = src_y,
- .y2 = src_y + src_h,
- };
-
- /* Rotate src coordinates to match rotated GTT view */
- drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
-
- src_x = r.x1;
- src_y = r.y1;
- src_w = drm_rect_width(&r);
- src_h = drm_rect_height(&r);
- }
-
- intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
- surf_addr = intel_compute_tile_offset(&src_x, &src_y, plane_state, 0);
-
/* Sizes are 0 based */
src_w--;
src_h--;
@@ -14224,6 +14318,7 @@ intel_check_primary_plane(struct drm_plane *plane,
int min_scale = DRM_PLANE_HELPER_NO_SCALING;
int max_scale = DRM_PLANE_HELPER_NO_SCALING;
bool can_position = false;
+ int ret;
if (INTEL_INFO(plane->dev)->gen >= 9) {
/* use scaler when colorkey is not required */
@@ -14234,11 +14329,24 @@ intel_check_primary_plane(struct drm_plane *plane,
can_position = true;
}
- return drm_plane_helper_check_update(plane, crtc, fb, &state->src,
- &state->dst, &state->clip,
- min_scale, max_scale,
- can_position, true,
- &state->visible);
+ ret = drm_plane_helper_check_update(plane, crtc, fb, &state->src,
+ &state->dst, &state->clip,
+ min_scale, max_scale,
+ can_position, true,
+ &state->visible);
+ if (ret)
+ return ret;
+
+ if (!fb)
+ return 0;
+
+ if (INTEL_INFO(plane->dev)->gen >= 9) {
+ ret = skl_check_plane_surface(state);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static void intel_begin_crtc_commit(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0c5e90f3b405..bdc793311a08 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -278,6 +278,10 @@ struct intel_plane_state {
struct drm_rect src;
struct drm_rect dst;
struct drm_rect clip;
+ struct {
+ u32 offset;
+ int x, y;
+ } main;
bool visible;
/*
@@ -1237,6 +1241,7 @@ u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
u32 skl_plane_ctl_rotation(unsigned int rotation);
u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane,
unsigned int rotation);
+int skl_check_plane_surface(struct intel_plane_state *plane_state);
/* intel_csr.c */
void intel_csr_ucode_init(struct drm_i915_private *);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 899dbb4d78a8..75bf01d05f7c 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -190,15 +190,15 @@ skl_update_plane(struct drm_plane *drm_plane,
const int plane = intel_plane->plane + 1;
u32 plane_ctl;
const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
- u32 surf_addr;
+ u32 surf_addr = plane_state->main.offset;
unsigned int rotation = plane_state->base.rotation;
u32 stride = skl_plane_stride(fb, 0, rotation);
int crtc_x = plane_state->dst.x1;
int crtc_y = plane_state->dst.y1;
uint32_t crtc_w = drm_rect_width(&plane_state->dst);
uint32_t crtc_h = drm_rect_height(&plane_state->dst);
- uint32_t x = plane_state->src.x1 >> 16;
- uint32_t y = plane_state->src.y1 >> 16;
+ uint32_t x = plane_state->main.x;
+ uint32_t y = plane_state->main.y;
uint32_t src_w = drm_rect_width(&plane_state->src) >> 16;
uint32_t src_h = drm_rect_height(&plane_state->src) >> 16;
const struct intel_scaler *scaler =
@@ -224,26 +224,6 @@ skl_update_plane(struct drm_plane *drm_plane,
else if (key->flags & I915_SET_COLORKEY_SOURCE)
plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
- if (intel_rotation_90_or_270(rotation)) {
- 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);
- }
-
- intel_add_fb_offsets(&x, &y, plane_state, 0);
- surf_addr = intel_compute_tile_offset(&x, &y, plane_state, 0);
-
/* Sizes are 0 based */
src_w--;
src_h--;
@@ -755,6 +735,7 @@ intel_check_sprite_plane(struct drm_plane *plane,
int hscale, vscale;
int max_scale, min_scale;
bool can_scale;
+ int ret;
if (!fb) {
state->visible = false;
@@ -909,6 +890,12 @@ intel_check_sprite_plane(struct drm_plane *plane,
dst->y1 = crtc_y;
dst->y2 = crtc_y + crtc_h;
+ if (INTEL_INFO(dev)->gen >= 9) {
+ ret = skl_check_plane_surface(state);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 20/21] drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (18 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 19/21] drm/i915: Compute display surface offset in the plane check hook for SKL+ ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-15 20:54 ` [PATCH v2 21/21] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
2016-02-16 11:28 ` ✗ Fi.CI.BAT: failure for drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) Patchwork
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 UTC (permalink / raw)
To: intel-gfx
From: Ville Syrjälä <ville.syrjala@linux.intel.com>
With NV12 we have two color planes to deal with so we must compute the
surface and x/y offsets for the second plane as well.
What makes this a bit nasty is that the hardware expects the surface
offset to be specified as a distance from the main surface offset.
What's worse, the distance must be non-negative (no neat wraparound or
anything). So we must make sure that the main surface offset is always
less or equal to the AUX surface offset. We do that by computing the AUX
offset first and the main surface offset second. If the main surface
offset ends up being above the AUX offset, we just push it down as far
as is required while still maintaining the required alignment etc.
Fortunately the AUX offset only reuqires 4K alignment, so we don't need
to do any of the backwards searching for an acceptable offset that we
must do for the main surface. And X tiled + NV12 isn't a supported
combination anyway.
TODO: actually program the HW registers
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 | 4 +++
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ad739f79e710..bb496c036049 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2633,8 +2633,14 @@ u32 intel_compute_tile_offset(int *x, int *y,
const struct drm_i915_private *dev_priv = to_i915(state->base.plane->dev);
const struct drm_framebuffer *fb = state->base.fb;
unsigned int rotation = state->base.rotation;
- u32 alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
int pitch = intel_fb_pitch(fb, plane, rotation);
+ u32 alignment;
+
+ /* AUX_DIST needs only 4K alignment */
+ if (fb->pixel_format == DRM_FORMAT_NV12 && plane == 1)
+ alignment = 4096;
+ else
+ alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
rotation, alignment);
@@ -3064,7 +3070,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
int h = drm_rect_height(&plane_state->src) >> 16;
int max_width = skl_max_plane_width(fb, 0, rotation);
int max_height = 4096;
- u32 alignment, offset;
+ u32 alignment, offset, aux_offset = plane_state->aux.offset;
if (w > max_width || h > max_height) {
DRM_DEBUG_KMS("requested Y/RGB source size %dx%d too big (limit %dx%d)\n",
@@ -3078,6 +3084,15 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
/*
+ * AUX surface offset is specified as the distance from the
+ * main surface offset, and it must be non-negative. Make
+ * sure that is what we will get.
+ */
+ if (offset > aux_offset)
+ offset = intel_adjust_tile_offset(&x, &y, plane_state, 0,
+ offset, aux_offset & ~(alignment - 1));
+
+ /*
* When using an X-tiled surface, the plane blows up
* if the x offset + width exceed the stride.
*
@@ -3107,6 +3122,35 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
return 0;
}
+static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->base.fb;
+ unsigned int rotation = plane_state->base.rotation;
+ int max_width = skl_max_plane_width(fb, 1, rotation);
+ int max_height = 4096;
+ int x = plane_state->src.x1 >> 17;
+ int y = plane_state->src.y1 >> 17;
+ int w = drm_rect_width(&plane_state->src) >> 17;
+ int h = drm_rect_height(&plane_state->src) >> 17;
+ u32 offset;
+
+ intel_add_fb_offsets(&x, &y, plane_state, 1);
+ offset = intel_compute_tile_offset(&x, &y, plane_state, 1);
+
+ /* FIXME not quite sure how/if these apply to the chroma plane */
+ if (w > max_width || h > max_height) {
+ DRM_DEBUG_KMS("CbCr source size %dx%d too big (limit %dx%d)\n",
+ w, h, max_width, max_height);
+ return -EINVAL;
+ }
+
+ plane_state->aux.offset = offset;
+ plane_state->aux.x = x;
+ plane_state->aux.y = y;
+
+ return 0;
+}
+
int skl_check_plane_surface(struct intel_plane_state *plane_state)
{
const struct drm_framebuffer *fb = plane_state->base.fb;
@@ -3118,6 +3162,20 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
drm_rect_rotate(&plane_state->src,
fb->width, fb->height, BIT(DRM_ROTATE_270));
+ /*
+ * Handle the AUX surface first since
+ * the main surface setup depends on it.
+ */
+ if (fb->pixel_format == DRM_FORMAT_NV12) {
+ ret = skl_check_nv12_aux_surface(plane_state);
+ if (ret)
+ return ret;
+ } else {
+ plane_state->aux.offset = ~0xfff;
+ plane_state->aux.x = 0;
+ plane_state->aux.y = 0;
+ }
+
ret = skl_check_main_surface(plane_state);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bdc793311a08..c7dab8d57274 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -282,6 +282,10 @@ struct intel_plane_state {
u32 offset;
int x, y;
} main;
+ struct {
+ u32 offset;
+ int x, y;
+ } aux;
bool visible;
/*
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH v2 21/21] drm/i915: Make sure fb offset is (macro)pixel aligned
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (19 preceding siblings ...)
2016-02-15 20:54 ` [PATCH 20/21] drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+ ville.syrjala
@ 2016-02-15 20:54 ` ville.syrjala
2016-02-16 11:28 ` ✗ Fi.CI.BAT: failure for drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) Patchwork
21 siblings, 0 replies; 36+ messages in thread
From: ville.syrjala @ 2016-02-15 20:54 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. Check for this, and if things look good
allow fb->offsets[] != 0 when creating fbs since we now handle
them correctly.
v2: Move to last place in the series and improve the commit message
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1)
---
drivers/gpu/drm/i915/intel_display.c | 37 +++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bb496c036049..db4a531e1d58 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15138,6 +15138,37 @@ 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 num_planes = drm_format_num_planes(format);
+ int i;
+
+ for (i = 0; i < num_planes; 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,
@@ -15276,9 +15307,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;
drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
intel_fb->obj = obj;
--
2.4.10
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 36+ messages in thread
* ✗ Fi.CI.BAT: failure for drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3)
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
` (20 preceding siblings ...)
2016-02-15 20:54 ` [PATCH v2 21/21] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
@ 2016-02-16 11:28 ` Patchwork
2016-02-25 17:46 ` Ville Syrjälä
21 siblings, 1 reply; 36+ messages in thread
From: Patchwork @ 2016-02-16 11:28 UTC (permalink / raw)
To: ville.syrjala; +Cc: intel-gfx
== Summary ==
Series 3455v1 drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3)
http://patchwork.freedesktop.org/api/1.0/series/3455/revisions/1/mbox/
Test gem_ringfill:
Subgroup basic-default-hang:
incomplete -> PASS (snb-dellxps)
Test gem_sync:
Subgroup basic-bsd:
dmesg-fail -> PASS (ilk-hp8440p)
Test kms_flip:
Subgroup basic-flip-vs-dpms:
dmesg-warn -> PASS (ilk-hp8440p) UNSTABLE
Subgroup basic-flip-vs-wf_vblank:
pass -> FAIL (snb-x220t)
Test kms_force_connector_basic:
Subgroup force-load-detect:
fail -> SKIP (ivb-t430s)
Test pm_rpm:
Subgroup basic-pci-d3-state:
pass -> FAIL (bdw-nuci7)
bdw-nuci7 total:162 pass:151 dwarn:0 dfail:0 fail:1 skip:10
bdw-ultra total:165 pass:152 dwarn:0 dfail:0 fail:0 skip:13
bsw-nuc-2 total:165 pass:135 dwarn:1 dfail:0 fail:0 skip:29
byt-nuc total:165 pass:140 dwarn:1 dfail:0 fail:0 skip:24
hsw-brixbox total:165 pass:151 dwarn:0 dfail:0 fail:0 skip:14
hsw-gt2 total:165 pass:154 dwarn:0 dfail:0 fail:1 skip:10
ilk-hp8440p total:165 pass:116 dwarn:0 dfail:0 fail:1 skip:48
ivb-t430s total:165 pass:150 dwarn:0 dfail:0 fail:0 skip:15
skl-i5k-2 total:165 pass:150 dwarn:0 dfail:0 fail:0 skip:15
snb-dellxps total:165 pass:142 dwarn:0 dfail:0 fail:1 skip:22
snb-x220t total:165 pass:141 dwarn:0 dfail:0 fail:3 skip:21
Results at /archive/results/CI_IGT_test/Patchwork_1410/
63cbdd1816fd78d404ed004b0f931c497625e0df drm-intel-nightly: 2016y-02m-16d-09h-41m-02s UTC integration manifest
b84ef2badea15712a81923b7df4706b24bc169ca drm/i915: Make sure fb offset is (macro)pixel aligned
ca71915fbb9c4c8ba57604ce6c8845fe03a43d7a drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+
d7f9294ecc8efdc5ee8ab82f507fbdfa908c85aa drm/i915: Compute display surface offset in the plane check hook for SKL+
8bef0691c82442ec596fdc70567f8c5e2811ae05 drm/i915: Make intel_adjust_tile_offset() work for linear buffers
1a99c9e2231d7e6f09606019ffe5adf7f0a80357 drm/i915: Allow calling intel_adjust_tile_offset() multiple times
c49b5375a08ed884e8606ef7d31a6715cbb25f0c drm/i915: Limit fb x offset due to fences
7491f5ca5dab46dd1a76cf29aafdfc0d4e98bb1e drm/i915: Adjust obj tiling vs. fb modifier rules
185515a0d9c827dc1cac159fcadd73b9fb90b679 drm/i915: Use fb modifiers for display tiling decisions
803c4b6df97ec77ea9d03f9c08df0937227533fb drm/i915: Pass around plane_state instead of fb+rotation
6b6b376594dcb603d281ec732e1e5059d6619384 drm/i915: Move SKL hw stride calculation into a helper
b06dc2a2512b136c01ff44537e003cfe83d7a819 drm/i915: Don't pass pitch to intel_compute_page_offset()
defd01e2e7134e7a4885520c20e957d3be3e1447 drm/i915: Rewrite fb rotation GTT handling
b160930772ba5b6c5288721316a1691f466b3359 drm/i915: Embed rotation_info under intel_framebuffer
5cac19f82e3eec58a3f5d804f4c1f381480193e4 drm/i915: Move the NULL sg handling out from rotate_pages()
2a89ffc5be0aee76cb70415a04f9df031b2f6f68 drm/i915: Reorganize intel_rotation_info
69bc06403bc4d1218a6b58ac5286e8fe7d68d1a4 drm/i915: Pass drm_frambuffer to intel_compute_page_offset()
1cf4455801c0ac86ea4c3634f96c725834244d09 drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
e83c7b76fb678f07f688db4b3e7aa7a0e057d742 drm/i915: Support for extra alignment for tiled surfaces
e685ff00fa6cb9d4a9511247cc272897f59ea71e drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
27fd3a6e846364496becb6cdada752ec905d6f1b drm/i915: s/tile_width/tile_width_bytes/
59b7e88935861c72c8f0ca8c3fcbe2cfe14a4d46 drm/i915: Account for the size of the chroma plane for the rotated gtt view
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view
2016-02-15 20:54 ` [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view ville.syrjala
@ 2016-02-16 11:40 ` Tvrtko Ursulin
2016-02-16 11:49 ` Ville Syrjälä
2016-02-17 12:51 ` Joonas Lahtinen
1 sibling, 1 reply; 36+ messages in thread
From: Tvrtko Ursulin @ 2016-02-16 11:40 UTC (permalink / raw)
To: ville.syrjala, intel-gfx
On 15/02/16 20:54, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The size of the rotated ggtt mapping ought to include the size of the
> chroma plane as well. Not a huge deal since we don't expose NV12 (or any
> pother planar format for that matter) yet.
>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Fixes: 9e759ff1f4a0 ("drm/i915: Return correct size for rotated views")
> 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 9127f8f3561c..4ccc8ec7003c 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -3636,7 +3636,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->params.rotated.size;
> + return view->params.rotated.size + view->params.rotated.size_uv;
> } else if (view->type == I915_GGTT_VIEW_PARTIAL) {
> return view->params.partial.size << PAGE_SHIFT;
> } else {
>
Oops! But the fixes tag is not correct. NV12 was added after the
referenced patch in:
commit 89e3e1427629027dc33e576fc002880a02a7e50c
Author: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Date: Mon Sep 21 10:45:34 2015 +0100
drm/i915: Support NV12 in rotated GGTT mapping
Anyway,
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
And no idea on what is the NV12 support status.
Regards,
Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view
2016-02-16 11:40 ` Tvrtko Ursulin
@ 2016-02-16 11:49 ` Ville Syrjälä
0 siblings, 0 replies; 36+ messages in thread
From: Ville Syrjälä @ 2016-02-16 11:49 UTC (permalink / raw)
To: Tvrtko Ursulin; +Cc: intel-gfx
On Tue, Feb 16, 2016 at 11:40:48AM +0000, Tvrtko Ursulin wrote:
>
>
> On 15/02/16 20:54, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > The size of the rotated ggtt mapping ought to include the size of the
> > chroma plane as well. Not a huge deal since we don't expose NV12 (or any
> > pother planar format for that matter) yet.
> >
> > Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> > Fixes: 9e759ff1f4a0 ("drm/i915: Return correct size for rotated views")
> > 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 9127f8f3561c..4ccc8ec7003c 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > @@ -3636,7 +3636,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->params.rotated.size;
> > + return view->params.rotated.size + view->params.rotated.size_uv;
> > } else if (view->type == I915_GGTT_VIEW_PARTIAL) {
> > return view->params.partial.size << PAGE_SHIFT;
> > } else {
> >
>
> Oops! But the fixes tag is not correct. NV12 was added after the
> referenced patch in:
>
> commit 89e3e1427629027dc33e576fc002880a02a7e50c
> Author: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Date: Mon Sep 21 10:45:34 2015 +0100
>
> drm/i915: Support NV12 in rotated GGTT mapping
I stand corrected.
>
> Anyway,
>
> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>
> And no idea on what is the NV12 support status.
Not there yet. There's a patch in the end of this series that adds some
AUX_DIST stuff. Beyond that we need to resurrect Chandra's NV12 patches
eventually.
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 02/21] drm/i915: s/tile_width/tile_width_bytes/
2016-02-15 20:54 ` [PATCH 02/21] drm/i915: s/tile_width/tile_width_bytes/ ville.syrjala
@ 2016-02-16 16:21 ` Daniel Vetter
0 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-02-16 16:21 UTC (permalink / raw)
To: ville.syrjala; +Cc: intel-gfx
On Mon, Feb 15, 2016 at 10:54:40PM +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Make if clear whether we're talking tile widths in bytes or in pixels.
>
> 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 | 32 ++++++++++++++++----------------
> 1 file changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4d30bca0b26b..acc632c06135 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2222,8 +2222,8 @@ 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)
> +static unsigned int intel_tile_width_bytes(const struct drm_i915_private *dev_priv,
> + uint64_t fb_modifier, unsigned int cpp)
> {
> switch (fb_modifier) {
> case DRM_FORMAT_MOD_NONE:
> @@ -2266,7 +2266,7 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
> return 1;
> else
> return intel_tile_size(dev_priv) /
> - intel_tile_width(dev_priv, fb_modifier, cpp);
> + intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
> }
>
> unsigned int
> @@ -2285,7 +2285,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->params.rotated;
> - unsigned int tile_size, tile_width, tile_height, cpp;
> + unsigned int tile_size, tile_width_bytes, tile_height, cpp;
>
> *view = i915_ggtt_view_normal;
>
> @@ -2306,19 +2306,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> tile_size = intel_tile_size(dev_priv);
>
> cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> - tile_width = intel_tile_width(dev_priv, fb->modifier[0], cpp);
> - tile_height = tile_size / tile_width;
> + tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[0], cpp);
> + tile_height = tile_size / tile_width_bytes;
>
> - info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
> + info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width_bytes);
> 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;
> + tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[1], cpp);
> + tile_height = tile_size / tile_width_bytes;
>
> - info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
> + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width_bytes);
> 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;
> }
> @@ -2455,18 +2455,18 @@ u32 intel_compute_tile_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_size, tile_width_bytes, tile_height;
> unsigned int tile_rows, tiles;
>
> tile_size = intel_tile_size(dev_priv);
> - tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
> - tile_height = tile_size / tile_width;
> + tile_width_bytes = intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
> + tile_height = tile_size / tile_width_bytes;
>
> tile_rows = *y / tile_height;
> *y %= tile_height;
>
> - tiles = *x / (tile_width/cpp);
> - *x %= tile_width/cpp;
> + tiles = *x / (tile_width_bytes/cpp);
> + *x %= tile_width_bytes/cpp;
>
> return tile_rows * pitch * tile_height + tiles * tile_size;
> } else {
> @@ -2928,7 +2928,7 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> } else {
> int cpp = drm_format_plane_cpp(pixel_format, 0);
>
> - return intel_tile_width(dev_priv, fb_modifier, cpp);
> + return intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
> }
> }
>
> --
> 2.4.10
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://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
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v4 03/21] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
2016-02-15 20:54 ` [PATCH v4 03/21] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
@ 2016-02-16 16:23 ` Daniel Vetter
0 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-02-16 16:23 UTC (permalink / raw)
To: ville.syrjala; +Cc: intel-gfx
On Mon, Feb 15, 2016 at 10:54:41PM +0200, 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
> v3: Introduce intel_tile_dims(), and don't mix up different units so much
> v4: Unconfuse bytes vs. pixels even more
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
I'm getting all funky staring at this once more ... But I think it still
looks correct, and it's definitely much less confusing.
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
> drivers/gpu/drm/i915/intel_display.c | 72 +++++++++++++++++++++++++-----------
> drivers/gpu/drm/i915/intel_drv.h | 3 +-
> drivers/gpu/drm/i915/intel_sprite.c | 18 +++++----
> 3 files changed, 63 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index acc632c06135..dcf379c29523 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2269,6 +2269,20 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
> intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
> }
>
> +/* Return the tile dimensions in pixel units */
> +static void intel_tile_dims(const struct drm_i915_private *dev_priv,
> + unsigned int *tile_width,
> + unsigned int *tile_height,
> + uint64_t fb_modifier,
> + unsigned int cpp)
> +{
> + unsigned int tile_width_bytes =
> + intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
> +
> + *tile_width = tile_width_bytes / cpp;
> + *tile_height = intel_tile_size(dev_priv) / tile_width_bytes;
> +}
> +
> unsigned int
> intel_fb_align_height(struct drm_device *dev, unsigned int height,
> uint32_t pixel_format, uint64_t fb_modifier)
> @@ -2285,7 +2299,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->params.rotated;
> - unsigned int tile_size, tile_width_bytes, tile_height, cpp;
> + unsigned int tile_size, tile_width, tile_height, cpp;
>
> *view = i915_ggtt_view_normal;
>
> @@ -2306,19 +2320,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
> tile_size = intel_tile_size(dev_priv);
>
> cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> - tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[0], cpp);
> - tile_height = tile_size / tile_width_bytes;
> + intel_tile_dims(dev_priv, &tile_width, &tile_height,
> + fb->modifier[0], cpp);
>
> - info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width_bytes);
> + info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
> 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_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[1], cpp);
> - tile_height = tile_size / tile_width_bytes;
> + intel_tile_dims(dev_priv, &tile_width, &tile_height,
> + fb->modifier[1], cpp);
>
> - info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width_bytes);
> + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
> 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;
> }
> @@ -2446,29 +2460,43 @@ 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. */
> +/*
> + * 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.
> + */
> u32 intel_compute_tile_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_bytes, tile_height;
> - unsigned int tile_rows, tiles;
> + unsigned int tile_size, tile_width, tile_height;
> + unsigned int tile_rows, tiles, pitch_tiles;
>
> tile_size = intel_tile_size(dev_priv);
> - tile_width_bytes = intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
> - tile_height = tile_size / tile_width_bytes;
> + intel_tile_dims(dev_priv, &tile_width, &tile_height,
> + fb_modifier, cpp);
> +
> + if (intel_rotation_90_or_270(rotation)) {
> + pitch_tiles = pitch / tile_height;
> + swap(tile_width, tile_height);
> + } else {
> + pitch_tiles = pitch / (tile_width * cpp);
> + }
>
> tile_rows = *y / tile_height;
> *y %= tile_height;
>
> - tiles = *x / (tile_width_bytes/cpp);
> - *x %= tile_width_bytes/cpp;
> + tiles = *x / tile_width;
> + *x %= tile_width;
>
> - return tile_rows * pitch * tile_height + tiles * tile_size;
> + return (tile_rows * pitch_tiles + tiles) * tile_size;
> } else {
> unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
> unsigned int offset;
> @@ -2713,6 +2741,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> u32 linear_offset;
> u32 dspcntr;
> i915_reg_t reg = DSPCNTR(plane);
> + unsigned int rotation = plane_state->base.rotation;
> int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> int x = plane_state->src.x1 >> 16;
> int y = plane_state->src.y1 >> 16;
> @@ -2779,13 +2808,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> intel_crtc->dspaddr_offset =
> intel_compute_tile_offset(dev_priv, &x, &y,
> fb->modifier[0], cpp,
> - fb->pitches[0]);
> + fb->pitches[0], rotation);
> linear_offset -= intel_crtc->dspaddr_offset;
> } else {
> intel_crtc->dspaddr_offset = linear_offset;
> }
>
> - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
> + if (rotation == BIT(DRM_ROTATE_180)) {
> dspcntr |= DISPPLANE_ROTATE_180;
>
> x += (crtc_state->pipe_src_w - 1);
> @@ -2843,6 +2872,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
> u32 linear_offset;
> u32 dspcntr;
> i915_reg_t reg = DSPCNTR(plane);
> + unsigned int rotation = plane_state->base.rotation;
> int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> int x = plane_state->src.x1 >> 16;
> int y = plane_state->src.y1 >> 16;
> @@ -2886,9 +2916,9 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
> intel_crtc->dspaddr_offset =
> intel_compute_tile_offset(dev_priv, &x, &y,
> fb->modifier[0], cpp,
> - fb->pitches[0]);
> + fb->pitches[0], rotation);
> linear_offset -= intel_crtc->dspaddr_offset;
> - if (plane_state->base.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 3cae3768ea37..7992e7a974f4 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1177,7 +1177,8 @@ u32 intel_compute_tile_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 a2582c455b36..7dc2b8b2a4ac 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -193,7 +193,7 @@ skl_update_plane(struct drm_plane *drm_plane,
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> u32 surf_addr;
> u32 tile_height, plane_offset, plane_size;
> - unsigned int rotation;
> + unsigned int rotation = plane_state->base.rotation;
> int x_offset, y_offset;
> int crtc_x = plane_state->dst.x1;
> int crtc_y = plane_state->dst.y1;
> @@ -213,7 +213,6 @@ skl_update_plane(struct drm_plane *drm_plane,
> plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
> plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
>
> - rotation = plane_state->base.rotation;
> plane_ctl |= skl_plane_ctl_rotation(rotation);
>
> stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> @@ -351,6 +350,7 @@ vlv_update_plane(struct drm_plane *dplane,
> int plane = intel_plane->plane;
> u32 sprctl;
> u32 sprsurf_offset, linear_offset;
> + unsigned int rotation = dplane->state->rotation;
> int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> int crtc_x = plane_state->dst.x1;
> @@ -425,10 +425,10 @@ vlv_update_plane(struct drm_plane *dplane,
> linear_offset = y * fb->pitches[0] + x * cpp;
> sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
> fb->modifier[0], cpp,
> - fb->pitches[0]);
> + fb->pitches[0], rotation);
> linear_offset -= sprsurf_offset;
>
> - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
> + if (rotation == BIT(DRM_ROTATE_180)) {
> sprctl |= SP_ROTATE_180;
>
> x += src_w;
> @@ -493,6 +493,7 @@ ivb_update_plane(struct drm_plane *plane,
> enum pipe pipe = intel_plane->pipe;
> u32 sprctl, sprscale = 0;
> u32 sprsurf_offset, linear_offset;
> + unsigned int rotation = plane_state->base.rotation;
> int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> int crtc_x = plane_state->dst.x1;
> @@ -558,10 +559,10 @@ ivb_update_plane(struct drm_plane *plane,
> linear_offset = y * fb->pitches[0] + x * cpp;
> sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
> fb->modifier[0], cpp,
> - fb->pitches[0]);
> + fb->pitches[0], rotation);
> linear_offset -= sprsurf_offset;
>
> - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
> + if (rotation == BIT(DRM_ROTATE_180)) {
> sprctl |= SPRITE_ROTATE_180;
>
> /* HSW and BDW does this automagically in hardware */
> @@ -634,6 +635,7 @@ ilk_update_plane(struct drm_plane *plane,
> int pipe = intel_plane->pipe;
> u32 dvscntr, dvsscale;
> u32 dvssurf_offset, linear_offset;
> + unsigned int rotation = plane_state->base.rotation;
> int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> int crtc_x = plane_state->dst.x1;
> @@ -695,10 +697,10 @@ ilk_update_plane(struct drm_plane *plane,
> linear_offset = y * fb->pitches[0] + x * cpp;
> dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
> fb->modifier[0], cpp,
> - fb->pitches[0]);
> + fb->pitches[0], rotation);
> linear_offset -= dvssurf_offset;
>
> - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
> + if (rotation == BIT(DRM_ROTATE_180)) {
> dvscntr |= DVS_ROTATE_180;
>
> x += src_w;
> --
> 2.4.10
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://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
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH v3 04/21] drm/i915: Support for extra alignment for tiled surfaces
2016-02-15 20:54 ` [PATCH v3 04/21] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
@ 2016-02-16 16:26 ` Daniel Vetter
0 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-02-16 16:26 UTC (permalink / raw)
To: ville.syrjala; +Cc: intel-gfx
On Mon, Feb 15, 2016 at 10:54:42PM +0200, 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.
>
> v2: Be less confusing wrt. units (pixels vs. bytes) (Daniel)
> v3: Use u32 for offsets
> Have intel_adjust_tile_offset() return the new offset (will be
> useful later)
> Add an offset_aligned variable (Daniel)
>
> 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 | 50 ++++++++++++++++++++++++++++++++----
> 1 file changed, 45 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index dcf379c29523..fe8d534a3334 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2461,6 +2461,35 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
> }
>
> /*
> + * Adjust the tile offset by moving the difference into
> + * the x/y offsets.
> + *
> + * Input tile dimensions and pitch must already be
> + * rotated to match x and y, and in pixel units.
> + */
> +static u32 intel_adjust_tile_offset(int *x, int *y,
> + unsigned int tile_width,
> + unsigned int tile_height,
> + unsigned int tile_size,
> + unsigned int pitch_tiles,
> + u32 old_offset,
> + u32 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;
> +
> + *y += tiles / pitch_tiles * tile_height;
> + *x += tiles % pitch_tiles * tile_width;
> +
> + return new_offset;
> +}
> +
> +/*
> * Computes the linear offset to the base tile and adjusts
> * x, y. bytes per pixel is assumed to be a power-of-two.
> *
> @@ -2475,6 +2504,12 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
> unsigned int pitch,
> unsigned int rotation)
> {
> + u32 offset, offset_aligned, 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, pitch_tiles;
> @@ -2496,16 +2531,21 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
> tiles = *x / tile_width;
> *x %= tile_width;
>
> - return (tile_rows * pitch_tiles + tiles) * tile_size;
> - } else {
> - unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
> - unsigned int offset;
> + offset = (tile_rows * pitch_tiles + tiles) * tile_size;
> + offset_aligned = offset & ~alignment;
>
> + intel_adjust_tile_offset(x, y, tile_width, tile_height,
> + tile_size, pitch_tiles,
> + offset, offset_aligned);
> + } else {
> offset = *y * pitch + *x * cpp;
> + offset_aligned = offset & ~alignment;
> +
> *y = (offset & alignment) / pitch;
> *x = ((offset & alignment) - *y * pitch) / cpp;
> - return offset & ~alignment;
> }
> +
> + return offset_aligned;
> }
>
> static int i9xx_format_to_fourcc(int format)
> --
> 2.4.10
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://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
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view
2016-02-15 20:54 ` [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view ville.syrjala
2016-02-16 11:40 ` Tvrtko Ursulin
@ 2016-02-17 12:51 ` Joonas Lahtinen
1 sibling, 0 replies; 36+ messages in thread
From: Joonas Lahtinen @ 2016-02-17 12:51 UTC (permalink / raw)
To: ville.syrjala, intel-gfx
Hi,
On ma, 2016-02-15 at 22:54 +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The size of the rotated ggtt mapping ought to include the size of the
> chroma plane as well. Not a huge deal since we don't expose NV12 (or any
> pother planar format for that matter) yet.
>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Fixes: 9e759ff1f4a0 ("drm/i915: Return correct size for rotated views")
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
A good catch. (That line even stays exactly below 80 character limit.)
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@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 9127f8f3561c..4ccc8ec7003c 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -3636,7 +3636,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->params.rotated.size;
> + return view->params.rotated.size + view->params.rotated.size_uv;
> } else if (view->type == I915_GGTT_VIEW_PARTIAL) {
> return view->params.partial.size << PAGE_SHIFT;
> } else {
--
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: ✗ Fi.CI.BAT: failure for drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3)
2016-02-16 11:28 ` ✗ Fi.CI.BAT: failure for drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) Patchwork
@ 2016-02-25 17:46 ` Ville Syrjälä
0 siblings, 0 replies; 36+ messages in thread
From: Ville Syrjälä @ 2016-02-25 17:46 UTC (permalink / raw)
To: intel-gfx
On Tue, Feb 16, 2016 at 11:28:05AM -0000, Patchwork wrote:
> == Summary ==
>
> Series 3455v1 drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3)
> http://patchwork.freedesktop.org/api/1.0/series/3455/revisions/1/mbox/
>
> Test gem_ringfill:
> Subgroup basic-default-hang:
> incomplete -> PASS (snb-dellxps)
> Test gem_sync:
> Subgroup basic-bsd:
> dmesg-fail -> PASS (ilk-hp8440p)
> Test kms_flip:
> Subgroup basic-flip-vs-dpms:
> dmesg-warn -> PASS (ilk-hp8440p) UNSTABLE
> Subgroup basic-flip-vs-wf_vblank:
> pass -> FAIL (snb-x220t)
(kms_flip:5932) DEBUG: name = flip
last_ts = 229.786169 usec
last_received_ts = 229.785609 usec
last_seq = 9555
current_ts = 229.970103 usec
current_received_ts = 229.983336 usec
current_seq = 9566
count = 30
seq_step = 1
(kms_flip:5932) CRITICAL: Test assertion failure function check_state, file kms_flip.c:692:
(kms_flip:5932) CRITICAL: Failed assertion: fabs((((double) diff.tv_usec) - usec_interflip) / usec_interflip) <= 0.005
(kms_flip:5932) CRITICAL: Last errno: 25, Inappropriate ioctl for device
(kms_flip:5932) CRITICAL: inter-flip ts jitter: 0s, 183934usec
Kinda looks like we were supposed to wait for 1 vblank and instead we
did 11. Not sure what happended.
> Test kms_force_connector_basic:
> Subgroup force-load-detect:
> fail -> SKIP (ivb-t430s)
> Test pm_rpm:
> Subgroup basic-pci-d3-state:
> pass -> FAIL (bdw-nuci7)
https://bugs.freedesktop.org/show_bug.cgi?id=94163
>
> bdw-nuci7 total:162 pass:151 dwarn:0 dfail:0 fail:1 skip:10
> bdw-ultra total:165 pass:152 dwarn:0 dfail:0 fail:0 skip:13
> bsw-nuc-2 total:165 pass:135 dwarn:1 dfail:0 fail:0 skip:29
> byt-nuc total:165 pass:140 dwarn:1 dfail:0 fail:0 skip:24
> hsw-brixbox total:165 pass:151 dwarn:0 dfail:0 fail:0 skip:14
> hsw-gt2 total:165 pass:154 dwarn:0 dfail:0 fail:1 skip:10
> ilk-hp8440p total:165 pass:116 dwarn:0 dfail:0 fail:1 skip:48
> ivb-t430s total:165 pass:150 dwarn:0 dfail:0 fail:0 skip:15
> skl-i5k-2 total:165 pass:150 dwarn:0 dfail:0 fail:0 skip:15
> snb-dellxps total:165 pass:142 dwarn:0 dfail:0 fail:1 skip:22
> snb-x220t total:165 pass:141 dwarn:0 dfail:0 fail:3 skip:21
>
> Results at /archive/results/CI_IGT_test/Patchwork_1410/
>
> 63cbdd1816fd78d404ed004b0f931c497625e0df drm-intel-nightly: 2016y-02m-16d-09h-41m-02s UTC integration manifest
> b84ef2badea15712a81923b7df4706b24bc169ca drm/i915: Make sure fb offset is (macro)pixel aligned
> ca71915fbb9c4c8ba57604ce6c8845fe03a43d7a drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+
> d7f9294ecc8efdc5ee8ab82f507fbdfa908c85aa drm/i915: Compute display surface offset in the plane check hook for SKL+
> 8bef0691c82442ec596fdc70567f8c5e2811ae05 drm/i915: Make intel_adjust_tile_offset() work for linear buffers
> 1a99c9e2231d7e6f09606019ffe5adf7f0a80357 drm/i915: Allow calling intel_adjust_tile_offset() multiple times
> c49b5375a08ed884e8606ef7d31a6715cbb25f0c drm/i915: Limit fb x offset due to fences
> 7491f5ca5dab46dd1a76cf29aafdfc0d4e98bb1e drm/i915: Adjust obj tiling vs. fb modifier rules
> 185515a0d9c827dc1cac159fcadd73b9fb90b679 drm/i915: Use fb modifiers for display tiling decisions
> 803c4b6df97ec77ea9d03f9c08df0937227533fb drm/i915: Pass around plane_state instead of fb+rotation
> 6b6b376594dcb603d281ec732e1e5059d6619384 drm/i915: Move SKL hw stride calculation into a helper
> b06dc2a2512b136c01ff44537e003cfe83d7a819 drm/i915: Don't pass pitch to intel_compute_page_offset()
> defd01e2e7134e7a4885520c20e957d3be3e1447 drm/i915: Rewrite fb rotation GTT handling
> b160930772ba5b6c5288721316a1691f466b3359 drm/i915: Embed rotation_info under intel_framebuffer
> 5cac19f82e3eec58a3f5d804f4c1f381480193e4 drm/i915: Move the NULL sg handling out from rotate_pages()
> 2a89ffc5be0aee76cb70415a04f9df031b2f6f68 drm/i915: Reorganize intel_rotation_info
> 69bc06403bc4d1218a6b58ac5286e8fe7d68d1a4 drm/i915: Pass drm_frambuffer to intel_compute_page_offset()
> 1cf4455801c0ac86ea4c3634f96c725834244d09 drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj()
> e83c7b76fb678f07f688db4b3e7aa7a0e057d742 drm/i915: Support for extra alignment for tiled surfaces
> e685ff00fa6cb9d4a9511247cc272897f59ea71e drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset()
> 27fd3a6e846364496becb6cdada752ec905d6f1b drm/i915: s/tile_width/tile_width_bytes/
> 59b7e88935861c72c8f0ca8c3fcbe2cfe14a4d46 drm/i915: Account for the size of the chroma plane for the rotated gtt view
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 09/21] drm/i915: Embed rotation_info under intel_framebuffer
2016-02-15 20:54 ` [PATCH 09/21] drm/i915: Embed rotation_info under intel_framebuffer ville.syrjala
@ 2016-03-01 11:00 ` Ville Syrjälä
0 siblings, 0 replies; 36+ messages in thread
From: Ville Syrjälä @ 2016-03-01 11:00 UTC (permalink / raw)
To: intel-gfx
On Mon, Feb 15, 2016 at 10:54:47PM +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Instead of repopulatin the rotation_info struct for the fb every time
> we try to use the fb, we can just populate it once when creating the fb,
> and later we can just copy the pre-populate struct into the gtt_view.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Merged up to here. Thanks for the reviews.
> ---
> drivers/gpu/drm/i915/intel_display.c | 27 ++++++++++++++++-----------
> drivers/gpu/drm/i915/intel_drv.h | 1 +
> 2 files changed, 17 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 74252433b1ec..fddfc5875752 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2309,18 +2309,20 @@ 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->params.rotated;
> - unsigned int tile_size, tile_width, tile_height, cpp;
> -
> - *view = i915_ggtt_view_normal;
> -
> - if (!intel_rotation_90_or_270(rotation))
> - return;
> -
> - *view = i915_ggtt_view_rotated;
> + if (intel_rotation_90_or_270(rotation)) {
> + *view = i915_ggtt_view_rotated;
> + view->params.rotated = to_intel_framebuffer(fb)->rot_info;
> + } else {
> + *view = i915_ggtt_view_normal;
> + }
> +}
>
> - info->uv_offset = fb->offsets[1];
> +static void
> +intel_fill_fb_info(struct drm_i915_private *dev_priv,
> + struct drm_framebuffer *fb)
> +{
> + struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info;
> + unsigned int tile_size, tile_width, tile_height, cpp;
>
> tile_size = intel_tile_size(dev_priv);
>
> @@ -2336,6 +2338,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> intel_tile_dims(dev_priv, &tile_width, &tile_height,
> fb->modifier[1], cpp);
>
> + info->uv_offset = fb->offsets[1];
> info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
> info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
> }
> @@ -14891,6 +14894,8 @@ 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_fill_fb_info(dev_priv, &intel_fb->base);
> +
> 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 59bed59388ad..674afa1f9f97 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -118,6 +118,7 @@ enum intel_output_type {
> struct intel_framebuffer {
> struct drm_framebuffer base;
> struct drm_i915_gem_object *obj;
> + struct intel_rotation_info rot_info;
> };
>
> struct intel_fbdev {
> --
> 2.4.10
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 15/21] drm/i915: Adjust obj tiling vs. fb modifier rules
2016-02-15 20:54 ` [PATCH 15/21] drm/i915: Adjust obj tiling vs. fb modifier rules ville.syrjala
@ 2016-03-17 8:08 ` Matthew Auld
0 siblings, 0 replies; 36+ messages in thread
From: Matthew Auld @ 2016-03-17 8:08 UTC (permalink / raw)
To: Ville Syrjälä; +Cc: intel-gfx
s/requite/require
s/presumaly/presumably
s/disalling/disabling
I think this makes sense so:
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 14/21] drm/i915: Use fb modifiers for display tiling decisions
2016-02-15 20:54 ` [PATCH 14/21] drm/i915: Use fb modifiers for display tiling decisions ville.syrjala
@ 2016-03-17 8:15 ` Matthew Auld
0 siblings, 0 replies; 36+ messages in thread
From: Matthew Auld @ 2016-03-17 8:15 UTC (permalink / raw)
To: Ville Syrjälä; +Cc: intel-gfx
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: FW: [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling
[not found] ` <DBEE2697754A7A4EAA940D4FF7143C6250E38A75@BGSMSX102.gar.corp.intel.com>
@ 2016-05-02 17:31 ` Thulasimani, Sivakumar
2016-05-02 18:40 ` Ville Syrjälä
0 siblings, 1 reply; 36+ messages in thread
From: Thulasimani, Sivakumar @ 2016-05-02 17:31 UTC (permalink / raw)
To: Mukherjee, Indranil, intel-gfx@lists.freedesktop.org,
Ville Syrjälä
sorry for the huge delay in reviewing this series, have just started on
this and could review only the first
patch for today, hopefully i'll continue on this everyday this week :).
replying as a detached thread since
i lost the mails as part original series so please forgive for the
detached reply for review.
On 5/2/2016 3:20 PM, Mukherjee, Indranil wrote:
>
> Regards,
> Indranil
>
> -----Original Message-----
> From: Intel-gfx [mailto:intel-gfx-bounces@lists.freedesktop.org] On Behalf Of ville.syrjala@linux.intel.com
> Sent: Tuesday, February 16, 2016 2:25 AM
> To: intel-gfx@lists.freedesktop.org
> Subject: [Intel-gfx] [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling
>
> 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
typo "easier"
> 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
> v3: Split out more changes to prep patches (Daniel)
> s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
> Rename intel_surf_gtt_offset to intel_fb_gtt_offset
> Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
> v4: Fix alignment vs. alignment-1 when calling
> _intel_compute_tile_offset() from intel_fill_fb_info()
> Pass the pitch in tiles in
> stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
> Pass the full width/height of the rotated area to
> drm_rect_rotate() for clarity
> Use u32 for more offsets
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_gem_gtt.c | 51 ++---
> drivers/gpu/drm/i915/i915_gem_gtt.h | 5 +-
> drivers/gpu/drm/i915/intel_display.c | 373 +++++++++++++++++++++++------------
> drivers/gpu/drm/i915/intel_drv.h | 19 +-
> drivers/gpu/drm/i915/intel_sprite.c | 97 ++++-----
> 5 files changed, 331 insertions(+), 214 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index 51f2597e3c56..5b17944a512b 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -3395,16 +3395,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 *rot_info,
> struct drm_i915_gem_object *obj)
> {
> - unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height;
> - unsigned int size_pages_uv;
> + unsigned int size = intel_rotation_info_size(rot_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;
>
> @@ -3414,18 +3412,12 @@ 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->plane[1].width * rot_info->plane[1].height;
> - 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;
>
> @@ -3439,32 +3431,14 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
> st->nents = 0;
> sg = st->sgl;
>
> - /* Rotate the pages. */
> - sg = rotate_pages(page_addr_list, 0,
> - rot_info->plane[0].width, rot_info->plane[0].height,
> - rot_info->plane[0].width,
> - st, sg);
> -
> - /* 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;
> -
> - sg = rotate_pages(page_addr_list, rot_info->uv_start_page,
> - rot_info->plane[1].width, rot_info->plane[1].height,
> - rot_info->plane[1].width,
> - st, sg);
> + for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++) {
> + sg = rotate_pages(page_addr_list, rot_info->plane[i].offset,
> + rot_info->plane[i].width, rot_info->plane[i].height,
> + rot_info->plane[i].stride, st, sg);
> }
>
> - DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
> - obj->base.size, rot_info->plane[0].width,
> - rot_info->plane[0].height, 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, rot_info->plane[0].width,
> +rot_info->plane[0].height, size);
>
> drm_free_large(page_addr_list);
>
> @@ -3475,10 +3449,9 @@ 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) (%ux%u tiles, %u pages (%u plane 0))\n",
> - obj->base.size, ret, rot_info->plane[0].width,
> - rot_info->plane[0].height, 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, rot_info->plane[0].width,
> +rot_info->plane[0].height, size);
> +
> return ERR_PTR(ret);
> }
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index 2fb98b1e4d82..89f34a920338 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -135,12 +135,9 @@ enum i915_ggtt_view_type { };
>
> struct intel_rotation_info {
> - unsigned int uv_offset;
> - uint32_t pixel_format;
> - unsigned int uv_start_page;
> struct {
> /* tiles */
> - unsigned int width, height;
> + unsigned int width, height, stride, offset;
> } plane[2];
> };
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index fddfc5875752..acd92f957054 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2317,33 +2317,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> }
> }
>
> -static void
> -intel_fill_fb_info(struct drm_i915_private *dev_priv,
> - struct drm_framebuffer *fb)
> -{
> - struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info;
> - unsigned int tile_size, tile_width, tile_height, cpp;
> -
> - tile_size = intel_tile_size(dev_priv);
> -
> - cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> - intel_tile_dims(dev_priv, &tile_width, &tile_height,
> - fb->modifier[0], cpp);
> -
> - info->plane[0].width = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
> - info->plane[0].height = DIV_ROUND_UP(fb->height, tile_height);
> -
> - if (info->pixel_format == DRM_FORMAT_NV12) {
> - cpp = drm_format_plane_cpp(fb->pixel_format, 1);
> - intel_tile_dims(dev_priv, &tile_width, &tile_height,
> - fb->modifier[1], cpp);
> -
> - info->uv_offset = fb->offsets[1];
> - info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
> - info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
> - }
> -}
> -
> static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv) {
> if (INTEL_INFO(dev_priv)->gen >= 9)
> @@ -2465,6 +2438,42 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation }
>
> /*
> + * 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.
> + */
> +u32 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;
> +}
> +
> +/*
> + * 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 intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> +
> + if (intel_rotation_90_or_270(rotation)) {
> + *x += intel_fb->rotated[plane].x;
> + *y += intel_fb->rotated[plane].y;
> + } else {
> + *x += intel_fb->normal[plane].x;
> + *y += intel_fb->normal[plane].y;
> + }
> +}
> +
> +/*
> * Adjust the tile offset by moving the difference into
> * the x/y offsets.
> *
> @@ -2500,18 +2509,24 @@ static u32 intel_adjust_tile_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.
> */
> -u32 intel_compute_tile_offset(int *x, int *y,
> - const struct drm_framebuffer *fb, int plane,
> - unsigned int pitch,
> - unsigned int rotation)
> +static u32 _intel_compute_tile_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,
> + u32 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);
> - u32 offset, offset_aligned, alignment;
> + u32 offset, offset_aligned;
>
> - alignment = intel_surf_alignment(dev_priv, fb_modifier);
> if (alignment)
> alignment--;
>
> @@ -2553,6 +2568,141 @@ u32 intel_compute_tile_offset(int *x, int *y,
> return offset_aligned;
> }
>
> +u32 intel_compute_tile_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);
> + u32 alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
> +
> + return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
> + rotation, alignment);
> +}
> +
> +/* 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];
> + u32 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 *rot_info = &intel_fb->rot_info;
> + u32 gtt_offset_rotated = 0;
> + unsigned int max_size = 0;
> + uint32_t format = fb->pixel_format;
> + int i, num_planes = drm_format_num_planes(format);
> + unsigned int tile_size = intel_tile_size(dev_priv);
> +
> + for (i = 0; i < num_planes; i++) {
> + unsigned int width, height;
> + unsigned int cpp, size;
> + u32 offset;
> + 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->normal[i].x = x;
> + intel_fb->normal[i].y = y;
> +
> + offset = _intel_compute_tile_offset(dev_priv, &x, &y,
> + fb, 0, fb->pitches[i],
> + BIT(DRM_ROTATE_0), tile_size);
> + offset /= tile_size;
> +
> + if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
> + unsigned int tile_width, tile_height;
> + unsigned int pitch_tiles;
> + struct drm_rect r;
> +
> + intel_tile_dims(dev_priv, &tile_width, &tile_height,
> + fb->modifier[i], cpp);
> +
> + rot_info->plane[i].offset = offset;
> + rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp);
> + rot_info->plane[i].width = DIV_ROUND_UP(x + width, tile_width);
> + rot_info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
> +
> + intel_fb->rotated[i].pitch =
> + rot_info->plane[i].height * tile_height;
> +
> + /* how many tiles does this plane need */
> + size = rot_info->plane[i].stride * rot_info->plane[i].height;
> + /*
> + * If the plane isn't horizontally tile aligned,
> + * we need one more tile.
> + */
> + if (x != 0)
> + size++;
> +
> + /* 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,
> + rot_info->plane[i].width * tile_width,
> + rot_info->plane[i].height * tile_height,
> + BIT(DRM_ROTATE_270));
> + x = r.x1;
> + y = r.y1;
> +
> + /* rotate the tile dimensions to match the GTT view */
> + pitch_tiles = intel_fb->rotated[i].pitch / tile_height;
> + swap(tile_width, tile_height);
> +
> + /*
> + * We only keep the x/y offsets, so push all of the
> + * gtt offset into the x/y offsets.
> + */
> + intel_adjust_tile_offset(&x, &y, tile_size,
> + tile_width, tile_height, pitch_tiles,
> + gtt_offset_rotated * tile_size, 0);
> +
> + gtt_offset_rotated += rot_info->plane[i].width *
> +rot_info->plane[i].height;
> +
> + /*
> + * First pixel of the framebuffer from
> + * the start of the rotated gtt mapping.
> + */
> + intel_fb->rotated[i].x = x;
> + intel_fb->rotated[i].y = y;
> + } else {
> + size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
> + x * cpp, tile_size);
> + }
> +
> + /* 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) {
> @@ -2787,7 +2937,6 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> u32 dspcntr;
> i915_reg_t reg = DSPCNTR(plane);
> unsigned int rotation = plane_state->base.rotation;
> - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> int x = plane_state->src.x1 >> 16;
> int y = plane_state->src.y1 >> 16;
>
> @@ -2847,30 +2996,25 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> if (IS_G4X(dev))
> dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
>
> - linear_offset = y * fb->pitches[0] + x * cpp;
> + 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_tile_offset(&x, &y, fb, 0,
> fb->pitches[0], rotation);
> - linear_offset -= intel_crtc->dspaddr_offset;
> - } else {
> - intel_crtc->dspaddr_offset = linear_offset;
> - }
>
> if (rotation == BIT(DRM_ROTATE_180)) {
> dspcntr |= DISPPLANE_ROTATE_180;
>
> x += (crtc_state->pipe_src_w - 1);
> y += (crtc_state->pipe_src_h - 1);
> -
> - /* Finding the last pixel of the last line of the display
> - data and adding to linear_offset*/
> - linear_offset +=
> - (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
> - (crtc_state->pipe_src_w - 1) * cpp;
> }
>
> + linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> +
> + if (INTEL_INFO(dev)->gen < 4)
> + intel_crtc->dspaddr_offset = linear_offset;
> +
basic question, the old code had linear_offset calculated first and then
x & y
were updated if rotation was set. the new code looks better since we handle
it after rotation but why not do the same for gen >= 4 too ? i.e move the
intel_compute_tile_offset after considering rotation ?
regards,
Sivakumar
> intel_crtc->adjusted_x = x;
> intel_crtc->adjusted_y = y;
>
> @@ -2879,7 +3023,8 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> 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_fb_gtt_offset(fb, rotation) +
> + intel_crtc->dspaddr_offset);
> I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
> I915_WRITE(DSPLINOFF(plane), linear_offset);
> } else
> @@ -2917,7 +3062,6 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
> u32 dspcntr;
> i915_reg_t reg = DSPCNTR(plane);
> unsigned int rotation = plane_state->base.rotation;
> - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> int x = plane_state->src.x1 >> 16;
> int y = plane_state->src.y1 >> 16;
>
> @@ -2956,26 +3100,23 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
> if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
> dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
>
> - linear_offset = y * fb->pitches[0] + x * cpp;
> + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> +
> intel_crtc->dspaddr_offset =
> intel_compute_tile_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 += (crtc_state->pipe_src_w - 1);
> y += (crtc_state->pipe_src_h - 1);
> -
> - /* Finding the last pixel of the last line of the display
> - data and adding to linear_offset*/
> - linear_offset +=
> - (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
> - (crtc_state->pipe_src_w - 1) * cpp;
> }
> }
>
> + linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> +
> intel_crtc->adjusted_x = x;
> intel_crtc->adjusted_y = y;
>
> @@ -2983,7 +3124,8 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
>
> I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
> I915_WRITE(DSPSURF(plane),
> - i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
> + intel_fb_gtt_offset(fb, rotation) +
> + intel_crtc->dspaddr_offset);
> if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
> } else {
> @@ -3005,32 +3147,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> }
> }
>
> -u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
> - struct drm_i915_gem_object *obj,
> - unsigned int plane)
> +u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
> + unsigned int rotation)
> {
> + struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> struct i915_ggtt_view view;
> - struct i915_vma *vma;
> - u64 offset;
> -
> - intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
> - intel_plane->base.state->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 = vma->node.start;
> -
> - if (plane == 1) {
> - offset += vma->ggtt_view.params.rotated.uv_start_page *
> - PAGE_SIZE;
> - }
> -
> - WARN_ON(upper_32_bits(offset));
> + intel_fill_fb_ggtt_view(&view, fb, rotation);
>
> - return lower_32_bits(offset);
> + return i915_gem_obj_ggtt_offset_view(obj, &view);
shouldnt we return lower_32_bits (i915_gem_obj_ggtt_offset_view(obj,
&view)) ? since it returns 64bit data
> }
>
> static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) @@ -3149,12 +3274,9 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
> struct drm_framebuffer *fb = plane_state->base.fb;
> - struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> int pipe = intel_crtc->pipe;
> u32 plane_ctl, stride_div, stride;
> - u32 tile_height, plane_offset, plane_size;
> unsigned int rotation = plane_state->base.rotation;
> - int x_offset, y_offset;
> u32 surf_addr;
> int scaler_id = plane_state->scaler_id;
> int src_x = plane_state->src.x1 >> 16; @@ -3175,36 +3297,49 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
> plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
> plane_ctl |= skl_plane_ctl_rotation(rotation);
>
> - 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);
> -
> if (intel_rotation_90_or_270(rotation)) {
> + struct drm_rect r = {
> + .x1 = src_x,
> + .x2 = src_x + src_w,
> + .y1 = src_y,
> + .y2 = src_y + src_h,
> + };
> int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> +
> + /* Rotate src coordinates to match rotated GTT view */
> + drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
>
> - /* stride = Surface height in tiles */
> - tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
> - stride = DIV_ROUND_UP(fb->height, tile_height);
> - x_offset = stride * tile_height - src_y - src_h;
> - y_offset = src_x;
> - plane_size = (src_w - 1) << 16 | (src_h - 1);
> + src_x = r.x1;
> + src_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], cpp);
> + stride = intel_fb->rotated[0].pitch;
> } else {
> - stride = fb->pitches[0] / stride_div;
> - x_offset = src_x;
> - y_offset = src_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(&src_x, &src_y, fb, 0, rotation);
> + surf_addr = intel_compute_tile_offset(&src_x, &src_y, fb, 0,
> + stride, rotation);
> +
> + /* Sizes are 0 based */
> + src_w--;
> + src_h--;
> + dst_w--;
> + dst_h--;
> +
> + intel_crtc->adjusted_x = src_x;
> + intel_crtc->adjusted_y = src_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), (src_y << 16) | src_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;
> @@ -3221,7 +3356,8 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
> 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_fb_gtt_offset(fb, rotation) + surf_addr);
>
> POSTING_READ(PLANE_SURF(pipe, 0));
> }
> @@ -11400,7 +11536,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
> const enum pipe pipe = intel_crtc->pipe;
> - u32 ctl, stride, tile_height;
> + u32 ctl, stride;
>
> ctl = I915_READ(PLANE_CTL(pipe, 0));
> ctl &= ~PLANE_CTL_TILED_MASK;
> @@ -11425,9 +11561,11 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
> * linear buffers or in number of tiles for tiled buffers.
> */
> if (intel_rotation_90_or_270(rotation)) {
> - /* stride = Surface height in tiles */
> - tile_height = intel_tile_height(dev_priv, fb->modifier[0], 0);
> - stride = DIV_ROUND_UP(fb->height, tile_height);
> + int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> +
> + stride = intel_fb->rotated[0].pitch /
> + intel_tile_height(dev_priv, fb->modifier[0], cpp);
> } else {
> stride = fb->pitches[0] /
> intel_fb_stride_alignment(dev_priv, fb->modifier[0], @@ -11753,8 +11891,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_fb_gtt_offset(fb, primary->state->rotation);
> work->gtt_offset += intel_crtc->dspaddr_offset;
>
> if (mmio_flip) {
> @@ -14759,7 +14896,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;
>
> @@ -14884,17 +15020,12 @@ static int intel_framebuffer_init(struct drm_device *dev,
> if (mode_cmd->offsets[0] != 0)
> return -EINVAL;
>
> - 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;
>
> - intel_fill_fb_info(dev_priv, &intel_fb->base);
> + 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) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 674afa1f9f97..84a2a3f109bb 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -119,6 +119,16 @@ struct intel_framebuffer {
> struct drm_framebuffer base;
> struct drm_i915_gem_object *obj;
> struct intel_rotation_info rot_info;
> +
> + /* for each plane in the normal GTT view */
> + struct {
> + unsigned int x, y;
> + } normal[2];
> + /* for each plane in the rotated GTT view */
> + struct {
> + unsigned int x, y;
> + unsigned int pitch; /* pixels */
> + } rotated[2];
> };
>
> struct intel_fbdev {
> @@ -1061,6 +1071,11 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
>
> /* intel_display.c */
> extern const struct drm_plane_funcs intel_plane_funcs;
> +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);
> unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info); bool intel_has_pending_fb_unpin(struct drm_device *dev); int intel_pch_rawclk(struct drm_device *dev); @@ -1217,9 +1232,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, 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);
>
> -u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
> - struct drm_i915_gem_object *obj,
> - unsigned int plane);
> +u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, 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 8821533561b1..86176304155d 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -186,15 +186,13 @@ skl_update_plane(struct drm_plane *drm_plane,
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct intel_plane *intel_plane = to_intel_plane(drm_plane);
> struct drm_framebuffer *fb = plane_state->base.fb;
> - 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;
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> u32 surf_addr;
> - u32 tile_height, plane_offset, plane_size;
> unsigned int rotation = plane_state->base.rotation;
> - int x_offset, y_offset;
> int crtc_x = plane_state->dst.x1;
> int crtc_y = plane_state->dst.y1;
> uint32_t crtc_w = drm_rect_width(&plane_state->dst);
> @@ -215,15 +213,6 @@ skl_update_plane(struct drm_plane *drm_plane,
>
> plane_ctl |= skl_plane_ctl_rotation(rotation);
>
> - stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> - fb->pixel_format);
> -
> - /* 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); @@ -235,28 +224,44 @@ skl_update_plane(struct drm_plane *drm_plane,
> 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)) {
> - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> -
> - /* stride: Surface height in tiles */
> - tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
> - 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,
> + };
> + unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> +
> + /* 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], cpp);
> + stride = intel_fb->rotated[0].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_tile_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 (plane_state->scaler_id >= 0) {
> @@ -278,7 +283,8 @@ skl_update_plane(struct drm_plane *drm_plane,
> }
>
> I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
> - I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
> + I915_WRITE(PLANE_SURF(pipe, plane),
> + intel_fb_gtt_offset(fb, rotation) + surf_addr);
> POSTING_READ(PLANE_SURF(pipe, plane)); }
>
> @@ -351,7 +357,6 @@ vlv_update_plane(struct drm_plane *dplane,
> u32 sprctl;
> u32 sprsurf_offset, linear_offset;
> unsigned int rotation = dplane->state->rotation;
> - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> int crtc_x = plane_state->dst.x1;
> int crtc_y = plane_state->dst.y1;
> @@ -422,19 +427,19 @@ vlv_update_plane(struct drm_plane *dplane,
> crtc_w--;
> crtc_h--;
>
> - linear_offset = y * fb->pitches[0] + x * cpp;
> + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> sprsurf_offset = intel_compute_tile_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 * cpp;
> }
>
> + 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); @@ -459,8 +464,8 @@ vlv_update_plane(struct drm_plane *dplane,
>
> 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_fb_gtt_offset(fb, rotation) + sprsurf_offset);
> POSTING_READ(SPSURF(pipe, plane));
> }
>
> @@ -493,7 +498,6 @@ ivb_update_plane(struct drm_plane *plane,
> u32 sprctl, sprscale = 0;
> u32 sprsurf_offset, linear_offset;
> unsigned int rotation = plane_state->base.rotation;
> - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> int crtc_x = plane_state->dst.x1;
> int crtc_y = plane_state->dst.y1;
> @@ -555,10 +559,9 @@ ivb_update_plane(struct drm_plane *plane,
> 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 * cpp;
> + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
> fb->pitches[0], rotation);
> - linear_offset -= sprsurf_offset;
>
> if (rotation == BIT(DRM_ROTATE_180)) {
> sprctl |= SPRITE_ROTATE_180;
> @@ -567,10 +570,11 @@ ivb_update_plane(struct drm_plane *plane,
> if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> x += src_w;
> y += src_h;
> - linear_offset += src_h * fb->pitches[0] + src_w * cpp;
> }
> }
>
> + 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); @@ -599,7 +603,7 @@ ivb_update_plane(struct drm_plane *plane,
> I915_WRITE(SPRSCALE(pipe), sprscale);
> I915_WRITE(SPRCTL(pipe), sprctl);
> I915_WRITE(SPRSURF(pipe),
> - i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
> + intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
> POSTING_READ(SPRSURF(pipe));
> }
>
> @@ -634,7 +638,6 @@ ilk_update_plane(struct drm_plane *plane,
> u32 dvscntr, dvsscale;
> u32 dvssurf_offset, linear_offset;
> unsigned int rotation = plane_state->base.rotation;
> - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> int crtc_x = plane_state->dst.x1;
> int crtc_y = plane_state->dst.y1;
> @@ -692,19 +695,19 @@ ilk_update_plane(struct drm_plane *plane,
> 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 * cpp;
> + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> dvssurf_offset = intel_compute_tile_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 * cpp;
> }
>
> + 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); @@ -728,7 +731,7 @@ ilk_update_plane(struct drm_plane *plane,
> I915_WRITE(DVSSCALE(pipe), dvsscale);
> I915_WRITE(DVSCNTR(pipe), dvscntr);
> I915_WRITE(DVSSURF(pipe),
> - i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
> + intel_fb_gtt_offset(fb, rotation) + dvssurf_offset);
> POSTING_READ(DVSSURF(pipe));
> }
>
> --
> 2.4.10
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: FW: [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling
2016-05-02 17:31 ` FW: " Thulasimani, Sivakumar
@ 2016-05-02 18:40 ` Ville Syrjälä
2016-05-02 18:48 ` Chris Wilson
0 siblings, 1 reply; 36+ messages in thread
From: Ville Syrjälä @ 2016-05-02 18:40 UTC (permalink / raw)
To: Thulasimani, Sivakumar; +Cc: intel-gfx@lists.freedesktop.org
On Mon, May 02, 2016 at 11:01:19PM +0530, Thulasimani, Sivakumar wrote:
> sorry for the huge delay in reviewing this series, have just started on
> this and could review only the first
> patch for today, hopefully i'll continue on this everyday this week :).
> replying as a detached thread since
> i lost the mails as part original series so please forgive for the
> detached reply for review.
>
> On 5/2/2016 3:20 PM, Mukherjee, Indranil wrote:
> >
> > Regards,
> > Indranil
> >
> > -----Original Message-----
> > From: Intel-gfx [mailto:intel-gfx-bounces@lists.freedesktop.org] On Behalf Of ville.syrjala@linux.intel.com
> > Sent: Tuesday, February 16, 2016 2:25 AM
> > To: intel-gfx@lists.freedesktop.org
> > Subject: [Intel-gfx] [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling
> >
> > 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
> typo "easier"
> > 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).
Your MUA seems to have mangled parts of the quoted mail rather
badly. Any chance you can tell it not to do that?
> >
> > 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
> > v3: Split out more changes to prep patches (Daniel)
> > s/intel_fb->plane[].foo.bar/intel_fb->foo[].bar/ for brevity
> > Rename intel_surf_gtt_offset to intel_fb_gtt_offset
> > Kill the pointless 'plane' parameter from intel_fb_gtt_offset()
> > v4: Fix alignment vs. alignment-1 when calling
> > _intel_compute_tile_offset() from intel_fill_fb_info()
> > Pass the pitch in tiles in
> > stad of pixels to intel_adjust_tile_offset() from intel_fill_fb_info()
> > Pass the full width/height of the rotated area to
> > drm_rect_rotate() for clarity
> > Use u32 for more offsets
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_gem_gtt.c | 51 ++---
> > drivers/gpu/drm/i915/i915_gem_gtt.h | 5 +-
> > drivers/gpu/drm/i915/intel_display.c | 373 +++++++++++++++++++++++------------
> > drivers/gpu/drm/i915/intel_drv.h | 19 +-
> > drivers/gpu/drm/i915/intel_sprite.c | 97 ++++-----
> > 5 files changed, 331 insertions(+), 214 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > index 51f2597e3c56..5b17944a512b 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > @@ -3395,16 +3395,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 *rot_info,
> > struct drm_i915_gem_object *obj)
> > {
> > - unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height;
> > - unsigned int size_pages_uv;
> > + unsigned int size = intel_rotation_info_size(rot_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;
> >
> > @@ -3414,18 +3412,12 @@ 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->plane[1].width * rot_info->plane[1].height;
> > - 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;
> >
> > @@ -3439,32 +3431,14 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
> > st->nents = 0;
> > sg = st->sgl;
> >
> > - /* Rotate the pages. */
> > - sg = rotate_pages(page_addr_list, 0,
> > - rot_info->plane[0].width, rot_info->plane[0].height,
> > - rot_info->plane[0].width,
> > - st, sg);
> > -
> > - /* 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;
> > -
> > - sg = rotate_pages(page_addr_list, rot_info->uv_start_page,
> > - rot_info->plane[1].width, rot_info->plane[1].height,
> > - rot_info->plane[1].width,
> > - st, sg);
> > + for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++) {
> > + sg = rotate_pages(page_addr_list, rot_info->plane[i].offset,
> > + rot_info->plane[i].width, rot_info->plane[i].height,
> > + rot_info->plane[i].stride, st, sg);
> > }
> >
> > - DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
> > - obj->base.size, rot_info->plane[0].width,
> > - rot_info->plane[0].height, 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, rot_info->plane[0].width,
> > +rot_info->plane[0].height, size);
> >
> > drm_free_large(page_addr_list);
> >
> > @@ -3475,10 +3449,9 @@ 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) (%ux%u tiles, %u pages (%u plane 0))\n",
> > - obj->base.size, ret, rot_info->plane[0].width,
> > - rot_info->plane[0].height, 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, rot_info->plane[0].width,
> > +rot_info->plane[0].height, size);
> > +
> > return ERR_PTR(ret);
> > }
> >
> > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > index 2fb98b1e4d82..89f34a920338 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > @@ -135,12 +135,9 @@ enum i915_ggtt_view_type { };
> >
> > struct intel_rotation_info {
> > - unsigned int uv_offset;
> > - uint32_t pixel_format;
> > - unsigned int uv_start_page;
> > struct {
> > /* tiles */
> > - unsigned int width, height;
> > + unsigned int width, height, stride, offset;
> > } plane[2];
> > };
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index fddfc5875752..acd92f957054 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2317,33 +2317,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> > }
> > }
> >
> > -static void
> > -intel_fill_fb_info(struct drm_i915_private *dev_priv,
> > - struct drm_framebuffer *fb)
> > -{
> > - struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info;
> > - unsigned int tile_size, tile_width, tile_height, cpp;
> > -
> > - tile_size = intel_tile_size(dev_priv);
> > -
> > - cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > - intel_tile_dims(dev_priv, &tile_width, &tile_height,
> > - fb->modifier[0], cpp);
> > -
> > - info->plane[0].width = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
> > - info->plane[0].height = DIV_ROUND_UP(fb->height, tile_height);
> > -
> > - if (info->pixel_format == DRM_FORMAT_NV12) {
> > - cpp = drm_format_plane_cpp(fb->pixel_format, 1);
> > - intel_tile_dims(dev_priv, &tile_width, &tile_height,
> > - fb->modifier[1], cpp);
> > -
> > - info->uv_offset = fb->offsets[1];
> > - info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
> > - info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
> > - }
> > -}
> > -
> > static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv) {
> > if (INTEL_INFO(dev_priv)->gen >= 9)
> > @@ -2465,6 +2438,42 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation }
> >
> > /*
> > + * 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.
> > + */
> > +u32 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;
> > +}
> > +
> > +/*
> > + * 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 intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +
> > + if (intel_rotation_90_or_270(rotation)) {
> > + *x += intel_fb->rotated[plane].x;
> > + *y += intel_fb->rotated[plane].y;
> > + } else {
> > + *x += intel_fb->normal[plane].x;
> > + *y += intel_fb->normal[plane].y;
> > + }
> > +}
> > +
> > +/*
> > * Adjust the tile offset by moving the difference into
> > * the x/y offsets.
> > *
> > @@ -2500,18 +2509,24 @@ static u32 intel_adjust_tile_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.
> > */
> > -u32 intel_compute_tile_offset(int *x, int *y,
> > - const struct drm_framebuffer *fb, int plane,
> > - unsigned int pitch,
> > - unsigned int rotation)
> > +static u32 _intel_compute_tile_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,
> > + u32 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);
> > - u32 offset, offset_aligned, alignment;
> > + u32 offset, offset_aligned;
> >
> > - alignment = intel_surf_alignment(dev_priv, fb_modifier);
> > if (alignment)
> > alignment--;
> >
> > @@ -2553,6 +2568,141 @@ u32 intel_compute_tile_offset(int *x, int *y,
> > return offset_aligned;
> > }
> >
> > +u32 intel_compute_tile_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);
> > + u32 alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
> > +
> > + return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
> > + rotation, alignment);
> > +}
> > +
> > +/* 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];
> > + u32 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 *rot_info = &intel_fb->rot_info;
> > + u32 gtt_offset_rotated = 0;
> > + unsigned int max_size = 0;
> > + uint32_t format = fb->pixel_format;
> > + int i, num_planes = drm_format_num_planes(format);
> > + unsigned int tile_size = intel_tile_size(dev_priv);
> > +
> > + for (i = 0; i < num_planes; i++) {
> > + unsigned int width, height;
> > + unsigned int cpp, size;
> > + u32 offset;
> > + 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->normal[i].x = x;
> > + intel_fb->normal[i].y = y;
> > +
> > + offset = _intel_compute_tile_offset(dev_priv, &x, &y,
> > + fb, 0, fb->pitches[i],
> > + BIT(DRM_ROTATE_0), tile_size);
> > + offset /= tile_size;
> > +
> > + if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
> > + unsigned int tile_width, tile_height;
> > + unsigned int pitch_tiles;
> > + struct drm_rect r;
> > +
> > + intel_tile_dims(dev_priv, &tile_width, &tile_height,
> > + fb->modifier[i], cpp);
> > +
> > + rot_info->plane[i].offset = offset;
> > + rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp);
> > + rot_info->plane[i].width = DIV_ROUND_UP(x + width, tile_width);
> > + rot_info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
> > +
> > + intel_fb->rotated[i].pitch =
> > + rot_info->plane[i].height * tile_height;
> > +
> > + /* how many tiles does this plane need */
> > + size = rot_info->plane[i].stride * rot_info->plane[i].height;
> > + /*
> > + * If the plane isn't horizontally tile aligned,
> > + * we need one more tile.
> > + */
> > + if (x != 0)
> > + size++;
> > +
> > + /* 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,
> > + rot_info->plane[i].width * tile_width,
> > + rot_info->plane[i].height * tile_height,
> > + BIT(DRM_ROTATE_270));
> > + x = r.x1;
> > + y = r.y1;
> > +
> > + /* rotate the tile dimensions to match the GTT view */
> > + pitch_tiles = intel_fb->rotated[i].pitch / tile_height;
> > + swap(tile_width, tile_height);
> > +
> > + /*
> > + * We only keep the x/y offsets, so push all of the
> > + * gtt offset into the x/y offsets.
> > + */
> > + intel_adjust_tile_offset(&x, &y, tile_size,
> > + tile_width, tile_height, pitch_tiles,
> > + gtt_offset_rotated * tile_size, 0);
> > +
> > + gtt_offset_rotated += rot_info->plane[i].width *
> > +rot_info->plane[i].height;
> > +
> > + /*
> > + * First pixel of the framebuffer from
> > + * the start of the rotated gtt mapping.
> > + */
> > + intel_fb->rotated[i].x = x;
> > + intel_fb->rotated[i].y = y;
> > + } else {
> > + size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
> > + x * cpp, tile_size);
> > + }
> > +
> > + /* 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) {
> > @@ -2787,7 +2937,6 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> > u32 dspcntr;
> > i915_reg_t reg = DSPCNTR(plane);
> > unsigned int rotation = plane_state->base.rotation;
> > - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > int x = plane_state->src.x1 >> 16;
> > int y = plane_state->src.y1 >> 16;
> >
> > @@ -2847,30 +2996,25 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> > if (IS_G4X(dev))
> > dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> >
> > - linear_offset = y * fb->pitches[0] + x * cpp;
> > + 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_tile_offset(&x, &y, fb, 0,
> > fb->pitches[0], rotation);
> > - linear_offset -= intel_crtc->dspaddr_offset;
> > - } else {
> > - intel_crtc->dspaddr_offset = linear_offset;
> > - }
> >
> > if (rotation == BIT(DRM_ROTATE_180)) {
> > dspcntr |= DISPPLANE_ROTATE_180;
> >
> > x += (crtc_state->pipe_src_w - 1);
> > y += (crtc_state->pipe_src_h - 1);
> > -
> > - /* Finding the last pixel of the last line of the display
> > - data and adding to linear_offset*/
> > - linear_offset +=
> > - (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
> > - (crtc_state->pipe_src_w - 1) * cpp;
> > }
> >
> > + linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> > + if (INTEL_INFO(dev)->gen < 4)
> > + intel_crtc->dspaddr_offset = linear_offset;
> > +
> basic question, the old code had linear_offset calculated first and then
> x & y
> were updated if rotation was set. the new code looks better since we handle
> it after rotation but why not do the same for gen >= 4 too ? i.e move the
> intel_compute_tile_offset after considering rotation ?
The hardware gets upset it you ask it to walk backwards past DSPSURF,
so DSPSURF must be below the entire scanned out surface. Hence we must
compute it before considering 180 degree rotation. Should probably add
a comment somewhere to explain that...
Hmm. Now that I think about this, the old code tried to play tricks to
compute both the linear and tiled offsets probably so that we could
switch tiling modes with CS flips without reprogramming the linear/x/y
offsets. But that can't actually work correctly unless the tile offset
is tile row aligned, which it might not be. So yeah, I think the
"change tiling mode with CS flips" thing was broken already, and still
will be after this patch.
>
> regards,
> Sivakumar
> > intel_crtc->adjusted_x = x;
> > intel_crtc->adjusted_y = y;
> >
> > @@ -2879,7 +3023,8 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
> > 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_fb_gtt_offset(fb, rotation) +
> > + intel_crtc->dspaddr_offset);
> > I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
> > I915_WRITE(DSPLINOFF(plane), linear_offset);
> > } else
> > @@ -2917,7 +3062,6 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
> > u32 dspcntr;
> > i915_reg_t reg = DSPCNTR(plane);
> > unsigned int rotation = plane_state->base.rotation;
> > - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > int x = plane_state->src.x1 >> 16;
> > int y = plane_state->src.y1 >> 16;
> >
> > @@ -2956,26 +3100,23 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
> > if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
> > dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> >
> > - linear_offset = y * fb->pitches[0] + x * cpp;
> > + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > +
> > intel_crtc->dspaddr_offset =
> > intel_compute_tile_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 += (crtc_state->pipe_src_w - 1);
> > y += (crtc_state->pipe_src_h - 1);
> > -
> > - /* Finding the last pixel of the last line of the display
> > - data and adding to linear_offset*/
> > - linear_offset +=
> > - (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
> > - (crtc_state->pipe_src_w - 1) * cpp;
> > }
> > }
> >
> > + linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> > intel_crtc->adjusted_x = x;
> > intel_crtc->adjusted_y = y;
> >
> > @@ -2983,7 +3124,8 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
> >
> > I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
> > I915_WRITE(DSPSURF(plane),
> > - i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
> > + intel_fb_gtt_offset(fb, rotation) +
> > + intel_crtc->dspaddr_offset);
> > if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> > I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
> > } else {
> > @@ -3005,32 +3147,15 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
> > }
> > }
> >
> > -u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
> > - struct drm_i915_gem_object *obj,
> > - unsigned int plane)
> > +u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
> > + unsigned int rotation)
> > {
> > + struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > struct i915_ggtt_view view;
> > - struct i915_vma *vma;
> > - u64 offset;
> > -
> > - intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
> > - intel_plane->base.state->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 = vma->node.start;
> > -
> > - if (plane == 1) {
> > - offset += vma->ggtt_view.params.rotated.uv_start_page *
> > - PAGE_SIZE;
> > - }
> > -
> > - WARN_ON(upper_32_bits(offset));
> > + intel_fill_fb_ggtt_view(&view, fb, rotation);
> >
> > - return lower_32_bits(offset);
> > + return i915_gem_obj_ggtt_offset_view(obj, &view);
> shouldnt we return lower_32_bits (i915_gem_obj_ggtt_offset_view(obj,
> &view)) ? since it returns 64bit data
Possibly. I think the lower_32_bits() stuff wasn't here when I made the
previous version(s) of this patch, and I just neglected to update this
part when rebasing. I guess we'll want to keep the WARN too.
> > }
> >
> > static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) @@ -3149,12 +3274,9 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
> > struct drm_i915_private *dev_priv = dev->dev_private;
> > struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
> > struct drm_framebuffer *fb = plane_state->base.fb;
> > - struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > int pipe = intel_crtc->pipe;
> > u32 plane_ctl, stride_div, stride;
> > - u32 tile_height, plane_offset, plane_size;
> > unsigned int rotation = plane_state->base.rotation;
> > - int x_offset, y_offset;
> > u32 surf_addr;
> > int scaler_id = plane_state->scaler_id;
> > int src_x = plane_state->src.x1 >> 16; @@ -3175,36 +3297,49 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
> > plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
> > plane_ctl |= skl_plane_ctl_rotation(rotation);
> >
> > - 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);
> > -
> > if (intel_rotation_90_or_270(rotation)) {
> > + struct drm_rect r = {
> > + .x1 = src_x,
> > + .x2 = src_x + src_w,
> > + .y1 = src_y,
> > + .y2 = src_y + src_h,
> > + };
> > int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +
> > + /* Rotate src coordinates to match rotated GTT view */
> > + drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
> >
> > - /* stride = Surface height in tiles */
> > - tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
> > - stride = DIV_ROUND_UP(fb->height, tile_height);
> > - x_offset = stride * tile_height - src_y - src_h;
> > - y_offset = src_x;
> > - plane_size = (src_w - 1) << 16 | (src_h - 1);
> > + src_x = r.x1;
> > + src_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], cpp);
> > + stride = intel_fb->rotated[0].pitch;
> > } else {
> > - stride = fb->pitches[0] / stride_div;
> > - x_offset = src_x;
> > - y_offset = src_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(&src_x, &src_y, fb, 0, rotation);
> > + surf_addr = intel_compute_tile_offset(&src_x, &src_y, fb, 0,
> > + stride, rotation);
> > +
> > + /* Sizes are 0 based */
> > + src_w--;
> > + src_h--;
> > + dst_w--;
> > + dst_h--;
> > +
> > + intel_crtc->adjusted_x = src_x;
> > + intel_crtc->adjusted_y = src_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), (src_y << 16) | src_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;
> > @@ -3221,7 +3356,8 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
> > 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_fb_gtt_offset(fb, rotation) + surf_addr);
> >
> > POSTING_READ(PLANE_SURF(pipe, 0));
> > }
> > @@ -11400,7 +11536,7 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
> > struct drm_i915_private *dev_priv = dev->dev_private;
> > struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
> > const enum pipe pipe = intel_crtc->pipe;
> > - u32 ctl, stride, tile_height;
> > + u32 ctl, stride;
> >
> > ctl = I915_READ(PLANE_CTL(pipe, 0));
> > ctl &= ~PLANE_CTL_TILED_MASK;
> > @@ -11425,9 +11561,11 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
> > * linear buffers or in number of tiles for tiled buffers.
> > */
> > if (intel_rotation_90_or_270(rotation)) {
> > - /* stride = Surface height in tiles */
> > - tile_height = intel_tile_height(dev_priv, fb->modifier[0], 0);
> > - stride = DIV_ROUND_UP(fb->height, tile_height);
> > + int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +
> > + stride = intel_fb->rotated[0].pitch /
> > + intel_tile_height(dev_priv, fb->modifier[0], cpp);
> > } else {
> > stride = fb->pitches[0] /
> > intel_fb_stride_alignment(dev_priv, fb->modifier[0], @@ -11753,8 +11891,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_fb_gtt_offset(fb, primary->state->rotation);
> > work->gtt_offset += intel_crtc->dspaddr_offset;
> >
> > if (mmio_flip) {
> > @@ -14759,7 +14896,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;
> >
> > @@ -14884,17 +15020,12 @@ static int intel_framebuffer_init(struct drm_device *dev,
> > if (mode_cmd->offsets[0] != 0)
> > return -EINVAL;
> >
> > - 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;
> >
> > - intel_fill_fb_info(dev_priv, &intel_fb->base);
> > + 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) {
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 674afa1f9f97..84a2a3f109bb 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -119,6 +119,16 @@ struct intel_framebuffer {
> > struct drm_framebuffer base;
> > struct drm_i915_gem_object *obj;
> > struct intel_rotation_info rot_info;
> > +
> > + /* for each plane in the normal GTT view */
> > + struct {
> > + unsigned int x, y;
> > + } normal[2];
> > + /* for each plane in the rotated GTT view */
> > + struct {
> > + unsigned int x, y;
> > + unsigned int pitch; /* pixels */
> > + } rotated[2];
> > };
> >
> > struct intel_fbdev {
> > @@ -1061,6 +1071,11 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
> >
> > /* intel_display.c */
> > extern const struct drm_plane_funcs intel_plane_funcs;
> > +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);
> > unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info); bool intel_has_pending_fb_unpin(struct drm_device *dev); int intel_pch_rawclk(struct drm_device *dev); @@ -1217,9 +1232,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, 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);
> >
> > -u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
> > - struct drm_i915_gem_object *obj,
> > - unsigned int plane);
> > +u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, 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 8821533561b1..86176304155d 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -186,15 +186,13 @@ skl_update_plane(struct drm_plane *drm_plane,
> > struct drm_i915_private *dev_priv = dev->dev_private;
> > struct intel_plane *intel_plane = to_intel_plane(drm_plane);
> > struct drm_framebuffer *fb = plane_state->base.fb;
> > - 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;
> > const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> > u32 surf_addr;
> > - u32 tile_height, plane_offset, plane_size;
> > unsigned int rotation = plane_state->base.rotation;
> > - int x_offset, y_offset;
> > int crtc_x = plane_state->dst.x1;
> > int crtc_y = plane_state->dst.y1;
> > uint32_t crtc_w = drm_rect_width(&plane_state->dst);
> > @@ -215,15 +213,6 @@ skl_update_plane(struct drm_plane *drm_plane,
> >
> > plane_ctl |= skl_plane_ctl_rotation(rotation);
> >
> > - stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > - fb->pixel_format);
> > -
> > - /* 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); @@ -235,28 +224,44 @@ skl_update_plane(struct drm_plane *drm_plane,
> > 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)) {
> > - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > -
> > - /* stride: Surface height in tiles */
> > - tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
> > - 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,
> > + };
> > + unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > +
> > + /* 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], cpp);
> > + stride = intel_fb->rotated[0].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_tile_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 (plane_state->scaler_id >= 0) {
> > @@ -278,7 +283,8 @@ skl_update_plane(struct drm_plane *drm_plane,
> > }
> >
> > I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
> > - I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
> > + I915_WRITE(PLANE_SURF(pipe, plane),
> > + intel_fb_gtt_offset(fb, rotation) + surf_addr);
> > POSTING_READ(PLANE_SURF(pipe, plane)); }
> >
> > @@ -351,7 +357,6 @@ vlv_update_plane(struct drm_plane *dplane,
> > u32 sprctl;
> > u32 sprsurf_offset, linear_offset;
> > unsigned int rotation = dplane->state->rotation;
> > - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> > int crtc_x = plane_state->dst.x1;
> > int crtc_y = plane_state->dst.y1;
> > @@ -422,19 +427,19 @@ vlv_update_plane(struct drm_plane *dplane,
> > crtc_w--;
> > crtc_h--;
> >
> > - linear_offset = y * fb->pitches[0] + x * cpp;
> > + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > sprsurf_offset = intel_compute_tile_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 * cpp;
> > }
> >
> > + 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); @@ -459,8 +464,8 @@ vlv_update_plane(struct drm_plane *dplane,
> >
> > 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_fb_gtt_offset(fb, rotation) + sprsurf_offset);
> > POSTING_READ(SPSURF(pipe, plane));
> > }
> >
> > @@ -493,7 +498,6 @@ ivb_update_plane(struct drm_plane *plane,
> > u32 sprctl, sprscale = 0;
> > u32 sprsurf_offset, linear_offset;
> > unsigned int rotation = plane_state->base.rotation;
> > - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> > int crtc_x = plane_state->dst.x1;
> > int crtc_y = plane_state->dst.y1;
> > @@ -555,10 +559,9 @@ ivb_update_plane(struct drm_plane *plane,
> > 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 * cpp;
> > + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
> > fb->pitches[0], rotation);
> > - linear_offset -= sprsurf_offset;
> >
> > if (rotation == BIT(DRM_ROTATE_180)) {
> > sprctl |= SPRITE_ROTATE_180;
> > @@ -567,10 +570,11 @@ ivb_update_plane(struct drm_plane *plane,
> > if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> > x += src_w;
> > y += src_h;
> > - linear_offset += src_h * fb->pitches[0] + src_w * cpp;
> > }
> > }
> >
> > + 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); @@ -599,7 +603,7 @@ ivb_update_plane(struct drm_plane *plane,
> > I915_WRITE(SPRSCALE(pipe), sprscale);
> > I915_WRITE(SPRCTL(pipe), sprctl);
> > I915_WRITE(SPRSURF(pipe),
> > - i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
> > + intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
> > POSTING_READ(SPRSURF(pipe));
> > }
> >
> > @@ -634,7 +638,6 @@ ilk_update_plane(struct drm_plane *plane,
> > u32 dvscntr, dvsscale;
> > u32 dvssurf_offset, linear_offset;
> > unsigned int rotation = plane_state->base.rotation;
> > - int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> > int crtc_x = plane_state->dst.x1;
> > int crtc_y = plane_state->dst.y1;
> > @@ -692,19 +695,19 @@ ilk_update_plane(struct drm_plane *plane,
> > 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 * cpp;
> > + intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > dvssurf_offset = intel_compute_tile_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 * cpp;
> > }
> >
> > + 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); @@ -728,7 +731,7 @@ ilk_update_plane(struct drm_plane *plane,
> > I915_WRITE(DVSSCALE(pipe), dvsscale);
> > I915_WRITE(DVSCNTR(pipe), dvscntr);
> > I915_WRITE(DVSSURF(pipe),
> > - i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
> > + intel_fb_gtt_offset(fb, rotation) + dvssurf_offset);
> > POSTING_READ(DVSSURF(pipe));
> > }
> >
> > --
> > 2.4.10
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: FW: [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling
2016-05-02 18:40 ` Ville Syrjälä
@ 2016-05-02 18:48 ` Chris Wilson
0 siblings, 0 replies; 36+ messages in thread
From: Chris Wilson @ 2016-05-02 18:48 UTC (permalink / raw)
To: Ville Syrjälä; +Cc: intel-gfx@lists.freedesktop.org
On Mon, May 02, 2016 at 09:40:45PM +0300, Ville Syrjälä wrote:
> On Mon, May 02, 2016 at 11:01:19PM +0530, Thulasimani, Sivakumar wrote:
> > basic question, the old code had linear_offset calculated first and then
> > x & y
> > were updated if rotation was set. the new code looks better since we handle
> > it after rotation but why not do the same for gen >= 4 too ? i.e move the
> > intel_compute_tile_offset after considering rotation ?
>
> The hardware gets upset it you ask it to walk backwards past DSPSURF,
> so DSPSURF must be below the entire scanned out surface. Hence we must
> compute it before considering 180 degree rotation. Should probably add
> a comment somewhere to explain that...
>
> Hmm. Now that I think about this, the old code tried to play tricks to
> compute both the linear and tiled offsets probably so that we could
> switch tiling modes with CS flips without reprogramming the linear/x/y
> offsets. But that can't actually work correctly unless the tile offset
> is tile row aligned, which it might not be. So yeah, I think the
> "change tiling mode with CS flips" thing was broken already, and still
> will be after this patch.
It is for a slightly different reason: emulating large (>8192 e.g.)
CRTC x/y offsets.
Changing tiling mode through flips should have been exercised (and I
guess a missed opportunity now would be to use i915.mmio_flips to force
that test case to exercise both CS and mmio flips explicitly).
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2016-05-02 18:48 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-15 20:54 [PATCH v3 00/21] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) ville.syrjala
2016-02-15 20:54 ` [PATCH 01/21] drm/i915: Account for the size of the chroma plane for the rotated gtt view ville.syrjala
2016-02-16 11:40 ` Tvrtko Ursulin
2016-02-16 11:49 ` Ville Syrjälä
2016-02-17 12:51 ` Joonas Lahtinen
2016-02-15 20:54 ` [PATCH 02/21] drm/i915: s/tile_width/tile_width_bytes/ ville.syrjala
2016-02-16 16:21 ` Daniel Vetter
2016-02-15 20:54 ` [PATCH v4 03/21] drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() ville.syrjala
2016-02-16 16:23 ` Daniel Vetter
2016-02-15 20:54 ` [PATCH v3 04/21] drm/i915: Support for extra alignment for tiled surfaces ville.syrjala
2016-02-16 16:26 ` Daniel Vetter
2016-02-15 20:54 ` [PATCH v2 05/21] drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() ville.syrjala
2016-02-15 20:54 ` [PATCH 06/21] drm/i915: Pass drm_frambuffer to intel_compute_page_offset() ville.syrjala
2016-02-15 20:54 ` [PATCH v2 07/21] drm/i915: Reorganize intel_rotation_info ville.syrjala
2016-02-15 20:54 ` [PATCH 08/21] drm/i915: Move the NULL sg handling out from rotate_pages() ville.syrjala
2016-02-15 20:54 ` [PATCH 09/21] drm/i915: Embed rotation_info under intel_framebuffer ville.syrjala
2016-03-01 11:00 ` Ville Syrjälä
2016-02-15 20:54 ` [PATCH v4 10/21] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
[not found] ` <DBEE2697754A7A4EAA940D4FF7143C6250E38A75@BGSMSX102.gar.corp.intel.com>
2016-05-02 17:31 ` FW: " Thulasimani, Sivakumar
2016-05-02 18:40 ` Ville Syrjälä
2016-05-02 18:48 ` Chris Wilson
2016-02-15 20:54 ` [PATCH v3 11/21] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
2016-02-15 20:54 ` [PATCH 12/21] drm/i915: Move SKL hw stride calculation into a helper ville.syrjala
2016-02-15 20:54 ` [PATCH 13/21] drm/i915: Pass around plane_state instead of fb+rotation ville.syrjala
2016-02-15 20:54 ` [PATCH 14/21] drm/i915: Use fb modifiers for display tiling decisions ville.syrjala
2016-03-17 8:15 ` Matthew Auld
2016-02-15 20:54 ` [PATCH 15/21] drm/i915: Adjust obj tiling vs. fb modifier rules ville.syrjala
2016-03-17 8:08 ` Matthew Auld
2016-02-15 20:54 ` [PATCH 16/21] drm/i915: Limit fb x offset due to fences ville.syrjala
2016-02-15 20:54 ` [PATCH 17/21] drm/i915: Allow calling intel_adjust_tile_offset() multiple times ville.syrjala
2016-02-15 20:54 ` [PATCH 18/21] drm/i915: Make intel_adjust_tile_offset() work for linear buffers ville.syrjala
2016-02-15 20:54 ` [PATCH 19/21] drm/i915: Compute display surface offset in the plane check hook for SKL+ ville.syrjala
2016-02-15 20:54 ` [PATCH 20/21] drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+ ville.syrjala
2016-02-15 20:54 ` [PATCH v2 21/21] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
2016-02-16 11:28 ` ✗ Fi.CI.BAT: failure for drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v3) Patchwork
2016-02-25 17:46 ` Ville Syrjälä
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).