From: Dave Airlie Date: Tue, 30 May 2017 05:25:28 +0000 (+1000) Subject: Merge tag 'drm-intel-next-2017-05-29' of git://anongit.freedesktop.org/git/drm-intel... X-Git-Tag: v4.13-rc1~45^2~32 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=a82256bc026722800d1fdeca5521f1ba487bc2ef;p=linux-2.6-block.git Merge tag 'drm-intel-next-2017-05-29' of git://anongit.freedesktop.org/git/drm-intel into drm-next More stuff for 4.13: - skl+ wm fixes from Mahesh Kumar - some refactor and tests for i915_sw_fence (Chris) - tune execlist/scheduler code (Chris) - g4x,g33 gpu reset improvements (Chris, Mika) - guc code cleanup (Michal Wajdeczko, MichaƂ Winiarski) - dp aux backlight improvements (Puthikorn Voravootivat) - buffer based guc/host communication (Michal Wajdeczko) * tag 'drm-intel-next-2017-05-29' of git://anongit.freedesktop.org/git/drm-intel: (253 commits) drm/i915: Update DRIVER_DATE to 20170529 drm/i915: Keep the forcewake timer alive for 1ms past the most recent use drm/i915/guc: capture GuC logs if FW fails to load drm/i915/guc: Introduce buffer based cmd transport drm/i915/guc: Disable send function on fini drm: Add definition for eDP backlight frequency drm/i915: Drop AUX backlight enable check for backlight control drm/i915: Consolidate #ifdef CONFIG_INTEL_IOMMU drm/i915: Only GGTT vma may be pinned and prevent shrinking drm/i915: Serialize GTT/Aperture accesses on BXT drm/i915: Convert i915_gem_object_ops->flags values to use BIT() drm/i915/selftests: Silence compiler warning in igt_ctx_exec drm/i915/guc: Skip port assign on first iteration of GuC dequeue drm/i915: Remove misleading comment in request_alloc drm/i915/g33: Improve reset reliability Revert "drm/i915: Restore lost "Initialized i915" welcome message" drm/i915/huc: Update GLK HuC version drm/i915: Check for allocation failure drm/i915/guc: Remove action status and statistics from debugfs drm/i915/g4x: Improve gpu reset reliability ... --- a82256bc026722800d1fdeca5521f1ba487bc2ef diff --cc drivers/gpu/drm/i915/intel_display.c index 6a037b856d96,55c2c149ad0b..7fa21df5bcd7 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@@ -9138,6 -9144,102 +9144,102 @@@ out return active; } + static u32 intel_cursor_base(const struct intel_plane_state *plane_state) + { + struct drm_i915_private *dev_priv = + to_i915(plane_state->base.plane->dev); + const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_i915_gem_object *obj = intel_fb_obj(fb); + u32 base; + + if (INTEL_INFO(dev_priv)->cursor_needs_physical) + base = obj->phys_handle->busaddr; + else + base = intel_plane_ggtt_offset(plane_state); + + base += plane_state->main.offset; + + /* ILK+ do this automagically */ + if (HAS_GMCH_DISPLAY(dev_priv) && - plane_state->base.rotation & DRM_ROTATE_180) ++ plane_state->base.rotation & DRM_MODE_ROTATE_180) + base += (plane_state->base.crtc_h * + plane_state->base.crtc_w - 1) * fb->format->cpp[0]; + + return base; + } + + static u32 intel_cursor_position(const struct intel_plane_state *plane_state) + { + int x = plane_state->base.crtc_x; + int y = plane_state->base.crtc_y; + u32 pos = 0; + + if (x < 0) { + pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; + x = -x; + } + pos |= x << CURSOR_X_SHIFT; + + if (y < 0) { + pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; + y = -y; + } + pos |= y << CURSOR_Y_SHIFT; + + return pos; + } + + static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state) + { + const struct drm_mode_config *config = + &plane_state->base.plane->dev->mode_config; + int width = plane_state->base.crtc_w; + int height = plane_state->base.crtc_h; + + return width > 0 && width <= config->cursor_width && + height > 0 && height <= config->cursor_height; + } + + static int intel_check_cursor(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) + { + const struct drm_framebuffer *fb = plane_state->base.fb; + int src_x, src_y; + u32 offset; + int ret; + + ret = drm_plane_helper_check_state(&plane_state->base, + &plane_state->clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); + if (ret) + return ret; + + if (!fb) + return 0; + + if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { + DRM_DEBUG_KMS("cursor cannot be tiled\n"); + return -EINVAL; + } + + src_x = plane_state->base.src_x >> 16; + src_y = plane_state->base.src_y >> 16; + + intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); + offset = intel_compute_tile_offset(&src_x, &src_y, plane_state, 0); + + if (src_x != 0 || src_y != 0) { + DRM_DEBUG_KMS("Arbitrary cursor panning not supported\n"); + return -EINVAL; + } + + plane_state->main.offset = offset; + + return 0; + } + static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@@ -9245,116 -9389,154 +9389,154 @@@ static u32 i9xx_cursor_ctl(const struc return cntl; } - static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, - const struct intel_plane_state *plane_state) + static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - uint32_t cntl = 0; + struct drm_i915_private *dev_priv = + to_i915(plane_state->base.plane->dev); + int width = plane_state->base.crtc_w; + int height = plane_state->base.crtc_h; - if (plane_state && plane_state->base.visible) - cntl = plane_state->ctl; + if (!intel_cursor_size_ok(plane_state)) + return false; - if (intel_crtc->cursor_cntl != cntl) { - I915_WRITE_FW(CURCNTR(pipe), cntl); - POSTING_READ_FW(CURCNTR(pipe)); - intel_crtc->cursor_cntl = cntl; + /* Cursor width is limited to a few power-of-two sizes */ + switch (width) { + case 256: + case 128: + case 64: + break; + default: + return false; } - /* and commit changes on next vblank */ - I915_WRITE_FW(CURBASE(pipe), base); - POSTING_READ_FW(CURBASE(pipe)); + /* + * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor + * height from 8 lines up to the cursor width, when the + * cursor is not rotated. Everything else requires square + * cursors. + */ + if (HAS_CUR_FBC(dev_priv) && - plane_state->base.rotation & DRM_ROTATE_0) { ++ plane_state->base.rotation & DRM_MODE_ROTATE_0) { + if (height < 8 || height > width) + return false; + } else { + if (height != width) + return false; + } - intel_crtc->cursor_base = base; + return true; } - /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ - static void intel_crtc_update_cursor(struct drm_crtc *crtc, - const struct intel_plane_state *plane_state) + static int i9xx_check_cursor(struct intel_plane *plane, + struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - u32 base = intel_crtc->cursor_addr; - unsigned long irqflags; - u32 pos = 0; - - if (plane_state) { - int x = plane_state->base.crtc_x; - int y = plane_state->base.crtc_y; + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + const struct drm_framebuffer *fb = plane_state->base.fb; + enum pipe pipe = plane->pipe; + int ret; - if (x < 0) { - pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; - x = -x; - } - pos |= x << CURSOR_X_SHIFT; + ret = intel_check_cursor(crtc_state, plane_state); + if (ret) + return ret; - if (y < 0) { - pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; - y = -y; - } - pos |= y << CURSOR_Y_SHIFT; + /* if we want to turn off the cursor ignore width and height */ + if (!fb) + return 0; - /* ILK+ do this automagically */ - if (HAS_GMCH_DISPLAY(dev_priv) && - plane_state->base.rotation & DRM_MODE_ROTATE_180) { - base += (plane_state->base.crtc_h * - plane_state->base.crtc_w - 1) * 4; - } + /* Check for which cursor types we support */ + if (!i9xx_cursor_size_ok(plane_state)) { + DRM_DEBUG("Cursor dimension %dx%d not supported\n", + plane_state->base.crtc_w, + plane_state->base.crtc_h); + return -EINVAL; } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (fb->pitches[0] != plane_state->base.crtc_w * fb->format->cpp[0]) { + DRM_DEBUG_KMS("Invalid cursor stride (%u) (cursor width %d)\n", + fb->pitches[0], plane_state->base.crtc_w); + return -EINVAL; + } - I915_WRITE_FW(CURPOS(pipe), pos); + /* + * There's something wrong with the cursor on CHV pipe C. + * If it straddles the left edge of the screen then + * moving it away from the edge or disabling it often + * results in a pipe underrun, and often that can lead to + * dead pipe (constant underrun reported, and it scans + * out just a solid color). To recover from that, the + * display power well must be turned off and on again. + * Refuse the put the cursor into that compromised position. + */ + if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C && + plane_state->base.visible && plane_state->base.crtc_x < 0) { + DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); + return -EINVAL; + } - if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) - i845_update_cursor(crtc, base, plane_state); - else - i9xx_update_cursor(crtc, base, plane_state); + plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + return 0; } - static bool cursor_size_ok(struct drm_i915_private *dev_priv, - uint32_t width, uint32_t height) + static void i9xx_update_cursor(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { - if (width == 0 || height == 0) - return false; + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum pipe pipe = plane->pipe; + u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0; + unsigned long irqflags; - /* - * 845g/865g are special in that they are only limited by - * the width of their cursors, the height is arbitrary up to - * the precision of the register. Everything else requires - * square cursors, limited to a few power-of-two sizes. - */ - if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) { - if ((width & 63) != 0) - return false; + if (plane_state && plane_state->base.visible) { + cntl = plane_state->ctl; - if (width > (IS_I845G(dev_priv) ? 64 : 512)) - return false; + if (plane_state->base.crtc_h != plane_state->base.crtc_w) + fbc_ctl = CUR_FBC_CTL_EN | (plane_state->base.crtc_h - 1); - if (height > 1023) - return false; + base = intel_cursor_base(plane_state); + pos = intel_cursor_position(plane_state); + } + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + /* + * On some platforms writing CURCNTR first will also + * cause CURPOS to be armed by the CURBASE write. + * Without the CURCNTR write the CURPOS write would + * arm itself. + * + * CURCNTR and CUR_FBC_CTL are always + * armed by the CURBASE write only. + */ + if (plane->cursor.base != base || + plane->cursor.size != fbc_ctl || + plane->cursor.cntl != cntl) { + I915_WRITE_FW(CURCNTR(pipe), cntl); + if (HAS_CUR_FBC(dev_priv)) + I915_WRITE_FW(CUR_FBC_CTL(pipe), fbc_ctl); + I915_WRITE_FW(CURPOS(pipe), pos); + I915_WRITE_FW(CURBASE(pipe), base); + + plane->cursor.base = base; + plane->cursor.size = fbc_ctl; + plane->cursor.cntl = cntl; } else { - switch (width | height) { - case 256: - case 128: - if (IS_GEN2(dev_priv)) - return false; - case 64: - break; - default: - return false; - } + I915_WRITE_FW(CURPOS(pipe), pos); } - return true; + POSTING_READ_FW(CURBASE(pipe)); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + } + + static void i9xx_disable_cursor(struct intel_plane *plane, + struct intel_crtc *crtc) + { + i9xx_update_cursor(plane, NULL, NULL); } + /* VESA 640x480x72Hz mode to set on the pipe */ static struct drm_display_mode load_detect_mode = { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,