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@xxxxxxxxx> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> 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@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx