[Intel-gfx] [PATCH] drm/i915: revert a few more watermark commits
Daniel Vetter
daniel at ffwll.ch
Tue Oct 13 05:00:04 PDT 2015
On Fri, Oct 09, 2015 at 06:22:43PM -0300, Paulo Zanoni wrote:
> This is a squash of the following commits:
>
> Revert "drm/i915: Drop intel_update_sprite_watermarks"
> This reverts commit 47c99438b52d12df50e182583634a4cfede3c920.
>
> Revert "drm/i915/ivb: Move WaCxSRDisabledForSpriteScaling w/a to atomic check"
> This reverts commit 7809e5ae35b9d8d0710f0874b2e3f10be144e38b.
>
> Revert "drm/i915/skl: Eliminate usage of pipe_wm_parameters from SKL-style WM (v3)"
> This reverts commit 3a05f5e2e78eab7ffe816abb59b6769e331a1957.
>
> With these reverts, SKL finally stops failing every single FBC test
> with FIFO underrun error messages. After some brief testing, it also
> seems that this commit prevents the machine from completely freezing
> when we run igt/kms_fbc_crc (see fd.o #92355).
>
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92355
> Cc: Matt Roper <matthew.d.roper at intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
Queued for -next, thanks for the patch.
-Daniel
> ---
> drivers/gpu/drm/i915/i915_drv.h | 4 +
> drivers/gpu/drm/i915/intel_atomic.c | 1 -
> drivers/gpu/drm/i915/intel_display.c | 44 +---
> drivers/gpu/drm/i915/intel_drv.h | 9 +-
> drivers/gpu/drm/i915/intel_pm.c | 419 +++++++++++++++++++++--------------
> drivers/gpu/drm/i915/intel_sprite.c | 15 ++
> 6 files changed, 293 insertions(+), 199 deletions(-)
>
>
> The fact that I needed more reverts after rebasing suggests that maybe the
> problem is happening due to some sort of timing problem? Maybe we're missing
> some lock?
>
> The machine freezes while running igt/kms_fbc_crc/blt are also curious, but I
> didn't spend too much time investigating them.
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index bf14096..22c8b0a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -628,6 +628,10 @@ struct drm_i915_display_funcs {
> struct dpll *match_clock,
> struct dpll *best_clock);
> void (*update_wm)(struct drm_crtc *crtc);
> + void (*update_sprite_wm)(struct drm_plane *plane,
> + struct drm_crtc *crtc,
> + uint32_t sprite_width, uint32_t sprite_height,
> + int pixel_size, bool enable, bool scaled);
> int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
> void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
> /* Returns the active state of the crtc, and if the crtc is active,
> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> index 05b1203..f1975f2 100644
> --- a/drivers/gpu/drm/i915/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/intel_atomic.c
> @@ -94,7 +94,6 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
> __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
>
> crtc_state->update_pipe = false;
> - crtc_state->disable_lp_wm = false;
>
> return &crtc_state->base;
> }
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index cddb0c6..66a37d8 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4804,6 +4804,7 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
> struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
> struct drm_device *dev = crtc->base.dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> + struct drm_plane *plane;
>
> if (atomic->wait_vblank)
> intel_wait_for_vblank(dev, crtc->pipe);
> @@ -4822,6 +4823,10 @@ static void intel_post_plane_update(struct intel_crtc *crtc)
> if (atomic->post_enable_primary)
> intel_post_enable_primary(&crtc->base);
>
> + drm_for_each_plane_mask(plane, dev, atomic->update_sprite_watermarks)
> + intel_update_sprite_watermarks(plane, &crtc->base,
> + 0, 0, 0, false, false);
> +
> memset(atomic, 0, sizeof(*atomic));
> }
>
> @@ -11577,30 +11582,16 @@ retry:
> static bool intel_wm_need_update(struct drm_plane *plane,
> struct drm_plane_state *state)
> {
> - struct intel_plane_state *new = to_intel_plane_state(state);
> - struct intel_plane_state *cur = to_intel_plane_state(plane->state);
> -
> - /* Update watermarks on tiling or size changes. */
> + /* Update watermarks on tiling changes. */
> if (!plane->state->fb || !state->fb ||
> plane->state->fb->modifier[0] != state->fb->modifier[0] ||
> - plane->state->rotation != state->rotation ||
> - drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
> - drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
> - drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
> - drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
> + plane->state->rotation != state->rotation)
> return true;
>
> - return false;
> -}
> -
> -static bool needs_scaling(struct intel_plane_state *state)
> -{
> - int src_w = drm_rect_width(&state->src) >> 16;
> - int src_h = drm_rect_height(&state->src) >> 16;
> - int dst_w = drm_rect_width(&state->dst);
> - int dst_h = drm_rect_height(&state->dst);
> + if (plane->state->crtc_w != state->crtc_w)
> + return true;
>
> - return (src_w != dst_w || src_h != dst_h);
> + return false;
> }
>
> int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> @@ -11618,6 +11609,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> bool mode_changed = needs_modeset(crtc_state);
> bool was_crtc_enabled = crtc->state->active;
> bool is_crtc_enabled = crtc_state->active;
> +
> bool turn_off, turn_on, visible, was_visible;
> struct drm_framebuffer *fb = plane_state->fb;
>
> @@ -11735,23 +11727,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
> case DRM_PLANE_TYPE_CURSOR:
> break;
> case DRM_PLANE_TYPE_OVERLAY:
> - /*
> - * WaCxSRDisabledForSpriteScaling:ivb
> - *
> - * cstate->update_wm was already set above, so this flag will
> - * take effect when we commit and program watermarks.
> - */
> - if (IS_IVYBRIDGE(dev) &&
> - needs_scaling(to_intel_plane_state(plane_state)) &&
> - !needs_scaling(old_plane_state)) {
> - to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
> - } else if (turn_off && !mode_changed) {
> + if (turn_off && !mode_changed) {
> intel_crtc->atomic.wait_vblank = true;
> intel_crtc->atomic.update_sprite_watermarks |=
> 1 << i;
> }
> -
> - break;
> }
> return 0;
> }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 91b6b40..0598932 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -468,9 +468,6 @@ struct intel_crtc_state {
>
> /* w/a for waiting 2 vblanks during crtc enable */
> enum pipe hsw_workaround_pipe;
> -
> - /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
> - bool disable_lp_wm;
> };
>
> struct vlv_wm_state {
> @@ -1399,6 +1396,12 @@ void intel_init_clock_gating(struct drm_device *dev);
> void intel_suspend_hw(struct drm_device *dev);
> int ilk_wm_max_level(const struct drm_device *dev);
> void intel_update_watermarks(struct drm_crtc *crtc);
> +void intel_update_sprite_watermarks(struct drm_plane *plane,
> + struct drm_crtc *crtc,
> + uint32_t sprite_width,
> + uint32_t sprite_height,
> + int pixel_size,
> + bool enabled, bool scaled);
> void intel_init_pm(struct drm_device *dev);
> void intel_pm_setup(struct drm_device *dev);
> void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index d031d74..d13551f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1765,6 +1765,13 @@ static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
> return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
> }
>
> +struct skl_pipe_wm_parameters {
> + bool active;
> + uint32_t pipe_htotal;
> + uint32_t pixel_rate; /* in KHz */
> + struct intel_plane_wm_parameters plane[I915_MAX_PLANES];
> +};
> +
> struct ilk_wm_maximums {
> uint16_t pri;
> uint16_t spr;
> @@ -2805,40 +2812,18 @@ static bool ilk_disable_lp_wm(struct drm_device *dev)
> #define SKL_DDB_SIZE 896 /* in blocks */
> #define BXT_DDB_SIZE 512
>
> -/*
> - * Return the index of a plane in the SKL DDB and wm result arrays. Primary
> - * plane is always in slot 0, cursor is always in slot I915_MAX_PLANES-1, and
> - * other universal planes are in indices 1..n. Note that this may leave unused
> - * indices between the top "sprite" plane and the cursor.
> - */
> -static int
> -skl_wm_plane_id(const struct intel_plane *plane)
> -{
> - switch (plane->base.type) {
> - case DRM_PLANE_TYPE_PRIMARY:
> - return 0;
> - case DRM_PLANE_TYPE_CURSOR:
> - return PLANE_CURSOR;
> - case DRM_PLANE_TYPE_OVERLAY:
> - return plane->plane + 1;
> - default:
> - MISSING_CASE(plane->base.type);
> - return plane->plane;
> - }
> -}
> -
> static void
> skl_ddb_get_pipe_allocation_limits(struct drm_device *dev,
> - const struct intel_crtc_state *cstate,
> + struct drm_crtc *for_crtc,
> const struct intel_wm_config *config,
> + const struct skl_pipe_wm_parameters *params,
> struct skl_ddb_entry *alloc /* out */)
> {
> - struct drm_crtc *for_crtc = cstate->base.crtc;
> struct drm_crtc *crtc;
> unsigned int pipe_size, ddb_size;
> int nth_active_pipe;
>
> - if (!cstate->base.active) {
> + if (!params->active) {
> alloc->start = 0;
> alloc->end = 0;
> return;
> @@ -2904,29 +2889,19 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> }
>
> static unsigned int
> -skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
> - const struct drm_plane_state *pstate,
> - int y)
> +skl_plane_relative_data_rate(const struct intel_plane_wm_parameters *p, int y)
> {
> - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
> - struct drm_framebuffer *fb = pstate->fb;
>
> /* for planar format */
> - if (fb->pixel_format == DRM_FORMAT_NV12) {
> + if (p->y_bytes_per_pixel) {
> if (y) /* y-plane data rate */
> - return intel_crtc->config->pipe_src_w *
> - intel_crtc->config->pipe_src_h *
> - drm_format_plane_cpp(fb->pixel_format, 0);
> + return p->horiz_pixels * p->vert_pixels * p->y_bytes_per_pixel;
> else /* uv-plane data rate */
> - return (intel_crtc->config->pipe_src_w/2) *
> - (intel_crtc->config->pipe_src_h/2) *
> - drm_format_plane_cpp(fb->pixel_format, 1);
> + return (p->horiz_pixels/2) * (p->vert_pixels/2) * p->bytes_per_pixel;
> }
>
> /* for packed formats */
> - return intel_crtc->config->pipe_src_w *
> - intel_crtc->config->pipe_src_h *
> - drm_format_plane_cpp(fb->pixel_format, 0);
> + return p->horiz_pixels * p->vert_pixels * p->bytes_per_pixel;
> }
>
> /*
> @@ -2935,51 +2910,46 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
> * 3 * 4096 * 8192 * 4 < 2^32
> */
> static unsigned int
> -skl_get_total_relative_data_rate(const struct intel_crtc_state *cstate)
> +skl_get_total_relative_data_rate(struct intel_crtc *intel_crtc,
> + const struct skl_pipe_wm_parameters *params)
> {
> - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
> - struct drm_device *dev = intel_crtc->base.dev;
> - const struct intel_plane *intel_plane;
> unsigned int total_data_rate = 0;
> + int plane;
>
> - for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
> - const struct drm_plane_state *pstate = intel_plane->base.state;
> + for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
> + const struct intel_plane_wm_parameters *p;
>
> - if (pstate->fb == NULL)
> + p = ¶ms->plane[plane];
> + if (!p->enabled)
> continue;
>
> - /* packed/uv */
> - total_data_rate += skl_plane_relative_data_rate(cstate,
> - pstate,
> - 0);
> -
> - if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
> - /* y-plane */
> - total_data_rate += skl_plane_relative_data_rate(cstate,
> - pstate,
> - 1);
> + total_data_rate += skl_plane_relative_data_rate(p, 0); /* packed/uv */
> + if (p->y_bytes_per_pixel) {
> + total_data_rate += skl_plane_relative_data_rate(p, 1); /* y-plane */
> + }
> }
>
> return total_data_rate;
> }
>
> static void
> -skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> +skl_allocate_pipe_ddb(struct drm_crtc *crtc,
> const struct intel_wm_config *config,
> + const struct skl_pipe_wm_parameters *params,
> struct skl_ddb_allocation *ddb /* out */)
> {
> - struct drm_crtc *crtc = cstate->base.crtc;
> struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> - struct intel_plane *intel_plane;
> enum pipe pipe = intel_crtc->pipe;
> struct skl_ddb_entry *alloc = &ddb->pipe[pipe];
> uint16_t alloc_size, start, cursor_blocks;
> uint16_t minimum[I915_MAX_PLANES];
> uint16_t y_minimum[I915_MAX_PLANES];
> unsigned int total_data_rate;
> + int plane;
>
> - skl_ddb_get_pipe_allocation_limits(dev, cstate, config, alloc);
> + skl_ddb_get_pipe_allocation_limits(dev, crtc, config, params, alloc);
> alloc_size = skl_ddb_entry_size(alloc);
> if (alloc_size == 0) {
> memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
> @@ -2996,20 +2966,17 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> alloc->end -= cursor_blocks;
>
> /* 1. Allocate the mininum required blocks for each active plane */
> - for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
> - struct drm_plane *plane = &intel_plane->base;
> - struct drm_framebuffer *fb = plane->fb;
> - int id = skl_wm_plane_id(intel_plane);
> + for_each_plane(dev_priv, pipe, plane) {
> + const struct intel_plane_wm_parameters *p;
>
> - if (fb == NULL)
> - continue;
> - if (plane->type == DRM_PLANE_TYPE_CURSOR)
> + p = ¶ms->plane[plane];
> + if (!p->enabled)
> continue;
>
> - minimum[id] = 8;
> - alloc_size -= minimum[id];
> - y_minimum[id] = (fb->pixel_format == DRM_FORMAT_NV12) ? 8 : 0;
> - alloc_size -= y_minimum[id];
> + minimum[plane] = 8;
> + alloc_size -= minimum[plane];
> + y_minimum[plane] = p->y_bytes_per_pixel ? 8 : 0;
> + alloc_size -= y_minimum[plane];
> }
>
> /*
> @@ -3018,50 +2985,45 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> *
> * FIXME: we may not allocate every single block here.
> */
> - total_data_rate = skl_get_total_relative_data_rate(cstate);
> + total_data_rate = skl_get_total_relative_data_rate(intel_crtc, params);
>
> start = alloc->start;
> - for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
> - struct drm_plane *plane = &intel_plane->base;
> - struct drm_plane_state *pstate = intel_plane->base.state;
> + for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) {
> + const struct intel_plane_wm_parameters *p;
> unsigned int data_rate, y_data_rate;
> uint16_t plane_blocks, y_plane_blocks = 0;
> - int id = skl_wm_plane_id(intel_plane);
>
> - if (pstate->fb == NULL)
> - continue;
> - if (plane->type == DRM_PLANE_TYPE_CURSOR)
> + p = ¶ms->plane[plane];
> + if (!p->enabled)
> continue;
>
> - data_rate = skl_plane_relative_data_rate(cstate, pstate, 0);
> + data_rate = skl_plane_relative_data_rate(p, 0);
>
> /*
> * allocation for (packed formats) or (uv-plane part of planar format):
> * promote the expression to 64 bits to avoid overflowing, the
> * result is < available as data_rate / total_data_rate < 1
> */
> - plane_blocks = minimum[id];
> + plane_blocks = minimum[plane];
> plane_blocks += div_u64((uint64_t)alloc_size * data_rate,
> total_data_rate);
>
> - ddb->plane[pipe][id].start = start;
> - ddb->plane[pipe][id].end = start + plane_blocks;
> + ddb->plane[pipe][plane].start = start;
> + ddb->plane[pipe][plane].end = start + plane_blocks;
>
> start += plane_blocks;
>
> /*
> * allocation for y_plane part of planar format:
> */
> - if (pstate->fb->pixel_format == DRM_FORMAT_NV12) {
> - y_data_rate = skl_plane_relative_data_rate(cstate,
> - pstate,
> - 1);
> - y_plane_blocks = y_minimum[id];
> + if (p->y_bytes_per_pixel) {
> + y_data_rate = skl_plane_relative_data_rate(p, 1);
> + y_plane_blocks = y_minimum[plane];
> y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
> total_data_rate);
>
> - ddb->y_plane[pipe][id].start = start;
> - ddb->y_plane[pipe][id].end = start + y_plane_blocks;
> + ddb->y_plane[pipe][plane].start = start;
> + ddb->y_plane[pipe][plane].end = start + y_plane_blocks;
>
> start += y_plane_blocks;
> }
> @@ -3148,21 +3110,87 @@ static void skl_compute_wm_global_parameters(struct drm_device *dev,
> struct intel_wm_config *config)
> {
> struct drm_crtc *crtc;
> + struct drm_plane *plane;
>
> list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> config->num_pipes_active += to_intel_crtc(crtc)->active;
> +
> + /* FIXME: I don't think we need those two global parameters on SKL */
> + list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> + struct intel_plane *intel_plane = to_intel_plane(plane);
> +
> + config->sprites_enabled |= intel_plane->wm.enabled;
> + config->sprites_scaled |= intel_plane->wm.scaled;
> + }
> +}
> +
> +static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc,
> + struct skl_pipe_wm_parameters *p)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> + enum pipe pipe = intel_crtc->pipe;
> + struct drm_plane *plane;
> + struct drm_framebuffer *fb;
> + int i = 1; /* Index for sprite planes start */
> +
> + p->active = intel_crtc->active;
> + if (p->active) {
> + p->pipe_htotal = intel_crtc->config->base.adjusted_mode.crtc_htotal;
> + p->pixel_rate = skl_pipe_pixel_rate(intel_crtc->config);
> +
> + fb = crtc->primary->state->fb;
> + /* For planar: Bpp is for uv plane, y_Bpp is for y plane */
> + if (fb) {
> + p->plane[0].enabled = true;
> + p->plane[0].bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
> + drm_format_plane_cpp(fb->pixel_format, 1) :
> + drm_format_plane_cpp(fb->pixel_format, 0);
> + p->plane[0].y_bytes_per_pixel = fb->pixel_format == DRM_FORMAT_NV12 ?
> + drm_format_plane_cpp(fb->pixel_format, 0) : 0;
> + p->plane[0].tiling = fb->modifier[0];
> + } else {
> + p->plane[0].enabled = false;
> + p->plane[0].bytes_per_pixel = 0;
> + p->plane[0].y_bytes_per_pixel = 0;
> + p->plane[0].tiling = DRM_FORMAT_MOD_NONE;
> + }
> + p->plane[0].horiz_pixels = intel_crtc->config->pipe_src_w;
> + p->plane[0].vert_pixels = intel_crtc->config->pipe_src_h;
> + p->plane[0].rotation = crtc->primary->state->rotation;
> +
> + fb = crtc->cursor->state->fb;
> + p->plane[PLANE_CURSOR].y_bytes_per_pixel = 0;
> + if (fb) {
> + p->plane[PLANE_CURSOR].enabled = true;
> + p->plane[PLANE_CURSOR].bytes_per_pixel = fb->bits_per_pixel / 8;
> + p->plane[PLANE_CURSOR].horiz_pixels = crtc->cursor->state->crtc_w;
> + p->plane[PLANE_CURSOR].vert_pixels = crtc->cursor->state->crtc_h;
> + } else {
> + p->plane[PLANE_CURSOR].enabled = false;
> + p->plane[PLANE_CURSOR].bytes_per_pixel = 0;
> + p->plane[PLANE_CURSOR].horiz_pixels = 64;
> + p->plane[PLANE_CURSOR].vert_pixels = 64;
> + }
> + }
> +
> + list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> + struct intel_plane *intel_plane = to_intel_plane(plane);
> +
> + if (intel_plane->pipe == pipe &&
> + plane->type == DRM_PLANE_TYPE_OVERLAY)
> + p->plane[i++] = intel_plane->wm;
> + }
> }
>
> static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> - struct intel_crtc_state *cstate,
> - struct intel_plane *intel_plane,
> + struct skl_pipe_wm_parameters *p,
> + struct intel_plane_wm_parameters *p_params,
> uint16_t ddb_allocation,
> int level,
> uint16_t *out_blocks, /* out */
> uint8_t *out_lines /* out */)
> {
> - struct drm_plane *plane = &intel_plane->base;
> - struct drm_framebuffer *fb = plane->state->fb;
> uint32_t latency = dev_priv->wm.skl_latency[level];
> uint32_t method1, method2;
> uint32_t plane_bytes_per_line, plane_blocks_per_line;
> @@ -3170,35 +3198,31 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> uint32_t selected_result;
> uint8_t bytes_per_pixel;
>
> - if (latency == 0 || !cstate->base.active || !fb)
> + if (latency == 0 || !p->active || !p_params->enabled)
> return false;
>
> - bytes_per_pixel = (fb->pixel_format == DRM_FORMAT_NV12) ?
> - drm_format_plane_cpp(DRM_FORMAT_NV12, 0) :
> - drm_format_plane_cpp(DRM_FORMAT_NV12, 1);
> - method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
> + bytes_per_pixel = p_params->y_bytes_per_pixel ?
> + p_params->y_bytes_per_pixel :
> + p_params->bytes_per_pixel;
> + method1 = skl_wm_method1(p->pixel_rate,
> bytes_per_pixel,
> latency);
> - method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
> - cstate->base.adjusted_mode.crtc_htotal,
> - cstate->pipe_src_w,
> + method2 = skl_wm_method2(p->pixel_rate,
> + p->pipe_htotal,
> + p_params->horiz_pixels,
> bytes_per_pixel,
> - fb->modifier[0],
> + p_params->tiling,
> latency);
>
> - plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel;
> + plane_bytes_per_line = p_params->horiz_pixels * bytes_per_pixel;
> plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
>
> - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
> - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
> + if (p_params->tiling == I915_FORMAT_MOD_Y_TILED ||
> + p_params->tiling == I915_FORMAT_MOD_Yf_TILED) {
> uint32_t min_scanlines = 4;
> uint32_t y_tile_minimum;
> - if (intel_rotation_90_or_270(plane->state->rotation)) {
> - int bpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
> - drm_format_plane_cpp(fb->pixel_format, 1) :
> - drm_format_plane_cpp(fb->pixel_format, 0);
> -
> - switch (bpp) {
> + if (intel_rotation_90_or_270(p_params->rotation)) {
> + switch (p_params->bytes_per_pixel) {
> case 1:
> min_scanlines = 16;
> break;
> @@ -3222,8 +3246,8 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line);
>
> if (level >= 1 && level <= 7) {
> - if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
> - fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)
> + if (p_params->tiling == I915_FORMAT_MOD_Y_TILED ||
> + p_params->tiling == I915_FORMAT_MOD_Yf_TILED)
> res_lines += 4;
> else
> res_blocks++;
> @@ -3240,80 +3264,84 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
>
> static void skl_compute_wm_level(const struct drm_i915_private *dev_priv,
> struct skl_ddb_allocation *ddb,
> - struct intel_crtc_state *cstate,
> + struct skl_pipe_wm_parameters *p,
> + enum pipe pipe,
> int level,
> + int num_planes,
> struct skl_wm_level *result)
> {
> - struct drm_device *dev = dev_priv->dev;
> - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
> - struct intel_plane *intel_plane;
> uint16_t ddb_blocks;
> - enum pipe pipe = intel_crtc->pipe;
> -
> - for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
> - int i = skl_wm_plane_id(intel_plane);
> + int i;
>
> + for (i = 0; i < num_planes; i++) {
> ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
>
> result->plane_en[i] = skl_compute_plane_wm(dev_priv,
> - cstate,
> - intel_plane,
> + p, &p->plane[i],
> ddb_blocks,
> level,
> &result->plane_res_b[i],
> &result->plane_res_l[i]);
> }
> +
> + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][PLANE_CURSOR]);
> + result->plane_en[PLANE_CURSOR] = skl_compute_plane_wm(dev_priv, p,
> + &p->plane[PLANE_CURSOR],
> + ddb_blocks, level,
> + &result->plane_res_b[PLANE_CURSOR],
> + &result->plane_res_l[PLANE_CURSOR]);
> }
>
> static uint32_t
> -skl_compute_linetime_wm(struct intel_crtc_state *cstate)
> +skl_compute_linetime_wm(struct drm_crtc *crtc, struct skl_pipe_wm_parameters *p)
> {
> - if (!cstate->base.active)
> + if (!to_intel_crtc(crtc)->active)
> return 0;
>
> - if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0))
> + if (WARN_ON(p->pixel_rate == 0))
> return 0;
>
> - return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000,
> - skl_pipe_pixel_rate(cstate));
> + return DIV_ROUND_UP(8 * p->pipe_htotal * 1000, p->pixel_rate);
> }
>
> -static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
> +static void skl_compute_transition_wm(struct drm_crtc *crtc,
> + struct skl_pipe_wm_parameters *params,
> struct skl_wm_level *trans_wm /* out */)
> {
> - struct drm_crtc *crtc = cstate->base.crtc;
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> - struct intel_plane *intel_plane;
> + int i;
>
> - if (!cstate->base.active)
> + if (!params->active)
> return;
>
> /* Until we know more, just disable transition WMs */
> - for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) {
> - int i = skl_wm_plane_id(intel_plane);
> -
> + for (i = 0; i < intel_num_planes(intel_crtc); i++)
> trans_wm->plane_en[i] = false;
> - }
> + trans_wm->plane_en[PLANE_CURSOR] = false;
> }
>
> -static void skl_compute_pipe_wm(struct intel_crtc_state *cstate,
> +static void skl_compute_pipe_wm(struct drm_crtc *crtc,
> struct skl_ddb_allocation *ddb,
> + struct skl_pipe_wm_parameters *params,
> struct skl_pipe_wm *pipe_wm)
> {
> - struct drm_device *dev = cstate->base.crtc->dev;
> + struct drm_device *dev = crtc->dev;
> const struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> int level, max_level = ilk_wm_max_level(dev);
>
> for (level = 0; level <= max_level; level++) {
> - skl_compute_wm_level(dev_priv, ddb, cstate,
> - level, &pipe_wm->wm[level]);
> + skl_compute_wm_level(dev_priv, ddb, params, intel_crtc->pipe,
> + level, intel_num_planes(intel_crtc),
> + &pipe_wm->wm[level]);
> }
> - pipe_wm->linetime = skl_compute_linetime_wm(cstate);
> + pipe_wm->linetime = skl_compute_linetime_wm(crtc, params);
>
> - skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
> + skl_compute_transition_wm(crtc, params, &pipe_wm->trans_wm);
> }
>
> static void skl_compute_wm_results(struct drm_device *dev,
> + struct skl_pipe_wm_parameters *p,
> struct skl_pipe_wm *p_wm,
> struct skl_wm_values *r,
> struct intel_crtc *intel_crtc)
> @@ -3557,15 +3585,16 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv,
> }
>
> static bool skl_update_pipe_wm(struct drm_crtc *crtc,
> + struct skl_pipe_wm_parameters *params,
> struct intel_wm_config *config,
> struct skl_ddb_allocation *ddb, /* out */
> struct skl_pipe_wm *pipe_wm /* out */)
> {
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> - struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
>
> - skl_allocate_pipe_ddb(cstate, config, ddb);
> - skl_compute_pipe_wm(cstate, ddb, pipe_wm);
> + skl_compute_wm_pipe_parameters(crtc, params);
> + skl_allocate_pipe_ddb(crtc, config, params, ddb);
> + skl_compute_pipe_wm(crtc, ddb, params, pipe_wm);
>
> if (!memcmp(&intel_crtc->wm.skl_active, pipe_wm, sizeof(*pipe_wm)))
> return false;
> @@ -3598,6 +3627,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
> */
> list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
> base.head) {
> + struct skl_pipe_wm_parameters params = {};
> struct skl_pipe_wm pipe_wm = {};
> bool wm_changed;
>
> @@ -3607,7 +3637,8 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
> if (!intel_crtc->active)
> continue;
>
> - wm_changed = skl_update_pipe_wm(&intel_crtc->base, config,
> + wm_changed = skl_update_pipe_wm(&intel_crtc->base,
> + ¶ms, config,
> &r->ddb, &pipe_wm);
>
> /*
> @@ -3617,7 +3648,7 @@ static void skl_update_other_pipe_wm(struct drm_device *dev,
> */
> WARN_ON(!wm_changed);
>
> - skl_compute_wm_results(dev, &pipe_wm, r, intel_crtc);
> + skl_compute_wm_results(dev, ¶ms, &pipe_wm, r, intel_crtc);
> r->dirty[intel_crtc->pipe] = true;
> }
> }
> @@ -3647,6 +3678,7 @@ static void skl_update_wm(struct drm_crtc *crtc)
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> struct drm_device *dev = crtc->dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> + struct skl_pipe_wm_parameters params = {};
> struct skl_wm_values *results = &dev_priv->wm.skl_results;
> struct skl_pipe_wm pipe_wm = {};
> struct intel_wm_config config = {};
> @@ -3659,10 +3691,11 @@ static void skl_update_wm(struct drm_crtc *crtc)
>
> skl_compute_wm_global_parameters(dev, &config);
>
> - if (!skl_update_pipe_wm(crtc, &config, &results->ddb, &pipe_wm))
> + if (!skl_update_pipe_wm(crtc, ¶ms, &config,
> + &results->ddb, &pipe_wm))
> return;
>
> - skl_compute_wm_results(dev, &pipe_wm, results, intel_crtc);
> + skl_compute_wm_results(dev, ¶ms, &pipe_wm, results, intel_crtc);
> results->dirty[intel_crtc->pipe] = true;
>
> skl_update_other_pipe_wm(dev, crtc, &config, results);
> @@ -3673,6 +3706,39 @@ static void skl_update_wm(struct drm_crtc *crtc)
> dev_priv->wm.skl_hw = *results;
> }
>
> +static void
> +skl_update_sprite_wm(struct drm_plane *plane, struct drm_crtc *crtc,
> + uint32_t sprite_width, uint32_t sprite_height,
> + int pixel_size, bool enabled, bool scaled)
> +{
> + struct intel_plane *intel_plane = to_intel_plane(plane);
> + struct drm_framebuffer *fb = plane->state->fb;
> +
> + intel_plane->wm.enabled = enabled;
> + intel_plane->wm.scaled = scaled;
> + intel_plane->wm.horiz_pixels = sprite_width;
> + intel_plane->wm.vert_pixels = sprite_height;
> + intel_plane->wm.tiling = DRM_FORMAT_MOD_NONE;
> +
> + /* For planar: Bpp is for UV plane, y_Bpp is for Y plane */
> + intel_plane->wm.bytes_per_pixel =
> + (fb && fb->pixel_format == DRM_FORMAT_NV12) ?
> + drm_format_plane_cpp(plane->state->fb->pixel_format, 1) : pixel_size;
> + intel_plane->wm.y_bytes_per_pixel =
> + (fb && fb->pixel_format == DRM_FORMAT_NV12) ?
> + drm_format_plane_cpp(plane->state->fb->pixel_format, 0) : 0;
> +
> + /*
> + * Framebuffer can be NULL on plane disable, but it does not
> + * matter for watermarks if we assume no tiling in that case.
> + */
> + if (fb)
> + intel_plane->wm.tiling = fb->modifier[0];
> + intel_plane->wm.rotation = plane->state->rotation;
> +
> + skl_update_wm(crtc);
> +}
> +
> static void ilk_update_wm(struct drm_crtc *crtc)
> {
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> @@ -3688,18 +3754,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
>
> WARN_ON(cstate->base.active != intel_crtc->active);
>
> - /*
> - * IVB workaround: must disable low power watermarks for at least
> - * one frame before enabling scaling. LP watermarks can be re-enabled
> - * when scaling is disabled.
> - *
> - * WaCxSRDisabledForSpriteScaling:ivb
> - */
> - if (cstate->disable_lp_wm) {
> - ilk_disable_lp_wm(dev);
> - intel_wait_for_vblank(dev, intel_crtc->pipe);
> - }
> -
> intel_compute_pipe_wm(cstate, &pipe_wm);
>
> if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
> @@ -3731,6 +3785,28 @@ static void ilk_update_wm(struct drm_crtc *crtc)
> ilk_write_wm_values(dev_priv, &results);
> }
>
> +static void
> +ilk_update_sprite_wm(struct drm_plane *plane,
> + struct drm_crtc *crtc,
> + uint32_t sprite_width, uint32_t sprite_height,
> + int pixel_size, bool enabled, bool scaled)
> +{
> + struct drm_device *dev = plane->dev;
> + struct intel_plane *intel_plane = to_intel_plane(plane);
> +
> + /*
> + * IVB workaround: must disable low power watermarks for at least
> + * one frame before enabling scaling. LP watermarks can be re-enabled
> + * when scaling is disabled.
> + *
> + * WaCxSRDisabledForSpriteScaling:ivb
> + */
> + if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
> + intel_wait_for_vblank(dev, intel_plane->pipe);
> +
> + ilk_update_wm(crtc);
> +}
> +
> static void skl_pipe_wm_active_state(uint32_t val,
> struct skl_pipe_wm *active,
> bool is_transwm,
> @@ -4108,6 +4184,21 @@ void intel_update_watermarks(struct drm_crtc *crtc)
> dev_priv->display.update_wm(crtc);
> }
>
> +void intel_update_sprite_watermarks(struct drm_plane *plane,
> + struct drm_crtc *crtc,
> + uint32_t sprite_width,
> + uint32_t sprite_height,
> + int pixel_size,
> + bool enabled, bool scaled)
> +{
> + struct drm_i915_private *dev_priv = plane->dev->dev_private;
> +
> + if (dev_priv->display.update_sprite_wm)
> + dev_priv->display.update_sprite_wm(plane, crtc,
> + sprite_width, sprite_height,
> + pixel_size, enabled, scaled);
> +}
> +
> /**
> * Lock protecting IPS related data structures
> */
> @@ -7022,6 +7113,7 @@ void intel_init_pm(struct drm_device *dev)
> dev_priv->display.init_clock_gating =
> skl_init_clock_gating;
> dev_priv->display.update_wm = skl_update_wm;
> + dev_priv->display.update_sprite_wm = skl_update_sprite_wm;
> } else if (HAS_PCH_SPLIT(dev)) {
> ilk_setup_wm_latency(dev);
>
> @@ -7030,6 +7122,7 @@ void intel_init_pm(struct drm_device *dev)
> (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
> dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
> dev_priv->display.update_wm = ilk_update_wm;
> + dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
> } else {
> DRM_DEBUG_KMS("Failed to read display plane latency. "
> "Disable CxSR\n");
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index dd2d568..b229c67 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -192,6 +192,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> const int pipe = intel_plane->pipe;
> const int plane = intel_plane->plane + 1;
> u32 plane_ctl, stride_div, stride;
> + int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> const struct drm_intel_sprite_colorkey *key =
> &to_intel_plane_state(drm_plane->state)->ckey;
> unsigned long surf_addr;
> @@ -210,6 +211,10 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
> rotation = drm_plane->state->rotation;
> plane_ctl |= skl_plane_ctl_rotation(rotation);
>
> + intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
> + pixel_size, true,
> + src_w != crtc_w || src_h != crtc_h);
> +
> stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> fb->pixel_format);
>
> @@ -291,6 +296,8 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
>
> I915_WRITE(PLANE_SURF(pipe, plane), 0);
> POSTING_READ(PLANE_SURF(pipe, plane));
> +
> + intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
> }
>
> static void
> @@ -533,6 +540,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> if (IS_HASWELL(dev) || IS_BROADWELL(dev))
> sprctl |= SPRITE_PIPE_CSC_ENABLE;
>
> + intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
> + true,
> + src_w != crtc_w || src_h != crtc_h);
> +
> /* Sizes are 0 based */
> src_w--;
> src_h--;
> @@ -666,6 +677,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
> if (IS_GEN6(dev))
> dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
>
> + intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
> + pixel_size, true,
> + src_w != crtc_w || src_h != crtc_h);
> +
> /* Sizes are 0 based */
> src_w--;
> src_h--;
> --
> 2.5.3
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the Intel-gfx
mailing list