From: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
To: ville.syrjala@linux.intel.com, intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 10/12] drm/i915: Compute display surface offset in the plane check hook for SKL+
Date: Mon, 9 May 2016 16:00:28 +0530 [thread overview]
Message-ID: <573066C4.8030907@intel.com> (raw)
In-Reply-To: <1462290001-9246-11-git-send-email-ville.syrjala@linux.intel.com>
Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com>
On Tuesday 03 May 2016 09:09 PM, ville.syrjala@linux.intel.com wrote:
> 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 ad7c48757ba6..b3d7d312e57c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2873,6 +2873,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)
> @@ -3252,10 +3366,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;
> @@ -3272,26 +3386,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--;
> @@ -14170,6 +14264,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 */
> @@ -14180,11 +14275,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 75e4d59f1ab3..fd4571d01304 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -318,6 +318,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;
>
> /*
> @@ -1288,6 +1292,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 ed46a84d97f7..02e840134ada 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;
> }
>
--
regards,
Sivakumar Thulasimani
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2016-05-09 10:25 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-03 15:39 [PATCH v4 00/12] drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v4) ville.syrjala
2016-05-03 15:39 ` [PATCH v5 01/12] drm/i915: Rewrite fb rotation GTT handling ville.syrjala
2016-05-05 8:12 ` Thulasimani, Sivakumar
2016-05-05 8:14 ` Thulasimani, Sivakumar
2016-05-03 15:39 ` [PATCH v3 02/12] drm/i915: Don't pass pitch to intel_compute_page_offset() ville.syrjala
2016-05-05 8:17 ` Thulasimani, Sivakumar
2016-05-03 15:39 ` [PATCH 03/12] drm/i915: Move SKL hw stride calculation into a helper ville.syrjala
2016-05-04 11:53 ` Matthew Auld
2016-05-05 8:20 ` Thulasimani, Sivakumar
2016-05-03 15:39 ` [PATCH 04/12] drm/i915: Pass around plane_state instead of fb+rotation ville.syrjala
2016-05-05 8:21 ` Thulasimani, Sivakumar
2016-05-03 15:39 ` [PATCH v2 05/12] drm/i915: Use fb modifiers for display tiling decisions ville.syrjala
2016-05-03 15:39 ` [PATCH v2 06/12] drm/i915: Adjust obj tiling vs. fb modifier rules ville.syrjala
2016-05-03 15:39 ` [PATCH 07/12] drm/i915: Limit fb x offset due to fences ville.syrjala
2016-05-05 10:19 ` Sivakumar Thulasimani
2016-05-03 15:39 ` [PATCH 08/12] drm/i915: Allow calling intel_adjust_tile_offset() multiple times ville.syrjala
2016-05-27 8:23 ` Ville Syrjälä
2016-05-30 10:14 ` Thulasimani, Sivakumar
2016-05-03 15:39 ` [PATCH 09/12] drm/i915: Make intel_adjust_tile_offset() work for linear buffers ville.syrjala
2016-05-09 9:24 ` Sivakumar Thulasimani
2016-05-03 15:39 ` [PATCH 10/12] drm/i915: Compute display surface offset in the plane check hook for SKL+ ville.syrjala
2016-05-09 10:30 ` Sivakumar Thulasimani [this message]
2016-05-03 15:40 ` [PATCH 11/12] drm/i915: Deal with NV12 CbCr plane AUX surface on SKL+ ville.syrjala
2016-05-03 15:40 ` [PATCH v2 12/12] drm/i915: Make sure fb offset is (macro)pixel aligned ville.syrjala
2016-05-03 16:25 ` ✗ Fi.CI.BAT: failure for drm/i915: Handle fb->offsets[] and rewrite fb rotation handling to be more generic (v4) Patchwork
2016-05-27 11:43 ` Ville Syrjälä
2016-05-27 11:49 ` Chris Wilson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=573066C4.8030907@intel.com \
--to=sivakumar.thulasimani@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=ville.syrjala@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.