From patchwork Wed Apr 9 21:44:31 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paulo Zanoni X-Patchwork-Id: 3957721 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id DDDA4BFF02 for ; Wed, 9 Apr 2014 21:44:59 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4732920592 for ; Wed, 9 Apr 2014 21:44:58 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 8A8022063F for ; Wed, 9 Apr 2014 21:44:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 253456EBD4; Wed, 9 Apr 2014 14:44:56 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-yk0-f170.google.com (mail-yk0-f170.google.com [209.85.160.170]) by gabe.freedesktop.org (Postfix) with ESMTP id 04E7C6EBD3 for ; Wed, 9 Apr 2014 14:44:54 -0700 (PDT) Received: by mail-yk0-f170.google.com with SMTP id 9so2793781ykp.29 for ; Wed, 09 Apr 2014 14:44:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=5FG9rZ1sxvm1DdJgfMbIqHM1wKbCYEfMob6z1Kq4hKI=; b=K1UlwhvOvN/+Yuf3pCy944rhdlwsYv2cnKOeF/VEoty4/3/fAxG+y8s7yZHN79hgP3 aq2PIuNOzg9M8KWanTacClerIkGPqc+ZjYnVeq2MAZJ1K1I/3HIKNAnZdxqRBnc2iA4s zXv13gSWh0z3RtgFI/uo7i7jcIhFS2f+6Z9WP06KRX8AE4LjIe7lGIdifASzVpsYdTQY yGltbAx6LEN9CnB5nmWZBL2edCm3jBce2MPIN/jVziLquu4JiX3y8yqsxwwllyPhm3ip YOtsX3x3A9kEK/cRMivDpZ1QK0GquqUO9AV+p2jAl5at13ZtTS/bCNfTHp9OTnru00T4 5mgQ== X-Received: by 10.236.206.7 with SMTP id k7mr17478949yho.84.1397079893531; Wed, 09 Apr 2014 14:44:53 -0700 (PDT) Received: from localhost.localdomain ([177.40.102.110]) by mx.google.com with ESMTPSA id f62sm3916352yhq.6.2014.04.09.14.44.51 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 09 Apr 2014 14:44:52 -0700 (PDT) From: Paulo Zanoni To: intel-gfx@lists.freedesktop.org Date: Wed, 9 Apr 2014 18:44:31 -0300 Message-Id: <1397079873-18257-3-git-send-email-przanoni@gmail.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1397079873-18257-1-git-send-email-przanoni@gmail.com> References: <1397079873-18257-1-git-send-email-przanoni@gmail.com> MIME-Version: 1.0 Cc: Paulo Zanoni Subject: [Intel-gfx] [PATCH 2/4] drm/i915: extract intel_cursor.c from intel_display.c X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Paulo Zanoni Since intel_display.c is way too big for our little heads. Signed-off-by: Paulo Zanoni --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/intel_cursor.c | 357 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 340 +-------------------------------- drivers/gpu/drm/i915/intel_drv.h | 18 ++ 4 files changed, 377 insertions(+), 339 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_cursor.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 1ec0317..dfc7993 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -34,6 +34,7 @@ i915-y += i915_cmd_parser.o \ # modesetting core code i915-y += intel_bios.o \ + intel_cursor.o \ intel_display.o \ intel_eld.o \ intel_modes.o \ diff --git a/drivers/gpu/drm/i915/intel_cursor.c b/drivers/gpu/drm/i915/intel_cursor.c new file mode 100644 index 0000000..a433f67 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_cursor.c @@ -0,0 +1,357 @@ +/* + * Copyright © 2006-2007, 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + */ + +#include "intel_drv.h" + +void assert_cursor(struct drm_i915_private *dev_priv, enum pipe pipe, + bool state) +{ + struct drm_device *dev = dev_priv->dev; + bool cur_state; + + if (IS_845G(dev) || IS_I865G(dev)) + cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE; + else if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) + cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; + else + cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE; + + WARN(cur_state != state, + "cursor on pipe %c assertion failure (expected %s, current %s)\n", + pipe_name(pipe), state_string(state), state_string(cur_state)); +} + +static void i845_update_cursor(struct drm_crtc *crtc, u32 base) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + bool visible = base != 0; + u32 cntl; + + if (intel_crtc->cursor_visible == visible) + return; + + cntl = I915_READ(_CURACNTR); + if (visible) { + /* On these chipsets we can only modify the base whilst + * the cursor is disabled. + */ + I915_WRITE(_CURABASE, base); + + cntl &= ~(CURSOR_FORMAT_MASK); + /* XXX width must be 64, stride 256 => 0x00 << 28 */ + cntl |= CURSOR_ENABLE | + CURSOR_GAMMA_ENABLE | + CURSOR_FORMAT_ARGB; + } else + cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); + I915_WRITE(_CURACNTR, cntl); + + intel_crtc->cursor_visible = visible; +} + +static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + bool visible = base != 0; + + if (intel_crtc->cursor_visible != visible) { + int16_t width = intel_crtc->cursor_width; + uint32_t cntl = I915_READ(CURCNTR(pipe)); + if (base) { + cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); + cntl |= MCURSOR_GAMMA_ENABLE; + + switch (width) { + case 64: + cntl |= CURSOR_MODE_64_ARGB_AX; + break; + case 128: + cntl |= CURSOR_MODE_128_ARGB_AX; + break; + case 256: + cntl |= CURSOR_MODE_256_ARGB_AX; + break; + default: + WARN_ON(1); + return; + } + cntl |= pipe << 28; /* Connect to correct pipe */ + } else { + cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); + cntl |= CURSOR_MODE_DISABLE; + } + I915_WRITE(CURCNTR(pipe), cntl); + + intel_crtc->cursor_visible = visible; + } + /* and commit changes on next vblank */ + POSTING_READ(CURCNTR(pipe)); + I915_WRITE(CURBASE(pipe), base); + POSTING_READ(CURBASE(pipe)); +} + +static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + bool visible = base != 0; + + if (intel_crtc->cursor_visible != visible) { + int16_t width = intel_crtc->cursor_width; + uint32_t cntl = I915_READ(CURCNTR_IVB(pipe)); + if (base) { + cntl &= ~CURSOR_MODE; + cntl |= MCURSOR_GAMMA_ENABLE; + switch (width) { + case 64: + cntl |= CURSOR_MODE_64_ARGB_AX; + break; + case 128: + cntl |= CURSOR_MODE_128_ARGB_AX; + break; + case 256: + cntl |= CURSOR_MODE_256_ARGB_AX; + break; + default: + WARN_ON(1); + return; + } + } else { + cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); + cntl |= CURSOR_MODE_DISABLE; + } + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + cntl |= CURSOR_PIPE_CSC_ENABLE; + cntl &= ~CURSOR_TRICKLE_FEED_DISABLE; + } + I915_WRITE(CURCNTR_IVB(pipe), cntl); + + intel_crtc->cursor_visible = visible; + } + /* and commit changes on next vblank */ + POSTING_READ(CURCNTR_IVB(pipe)); + I915_WRITE(CURBASE_IVB(pipe), base); + POSTING_READ(CURBASE_IVB(pipe)); +} + +/* If no-part of the cursor is visible on the framebuffer, then the GPU may + * hang... */ +void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + int x = intel_crtc->cursor_x; + int y = intel_crtc->cursor_y; + u32 base = 0, pos = 0; + bool visible; + + if (on) + base = intel_crtc->cursor_addr; + + if (x >= intel_crtc->config.pipe_src_w) + base = 0; + + if (y >= intel_crtc->config.pipe_src_h) + base = 0; + + if (x < 0) { + if (x + intel_crtc->cursor_width <= 0) + base = 0; + + pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; + x = -x; + } + pos |= x << CURSOR_X_SHIFT; + + if (y < 0) { + if (y + intel_crtc->cursor_height <= 0) + base = 0; + + pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; + y = -y; + } + pos |= y << CURSOR_Y_SHIFT; + + visible = base != 0; + if (!visible && !intel_crtc->cursor_visible) + return; + + if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) { + I915_WRITE(CURPOS_IVB(pipe), pos); + ivb_update_cursor(crtc, base); + } else { + I915_WRITE(CURPOS(pipe), pos); + if (IS_845G(dev) || IS_I865G(dev)) + i845_update_cursor(crtc, base); + else + i9xx_update_cursor(crtc, base); + } +} + +int intel_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file, + uint32_t handle, + uint32_t width, uint32_t height) +{ + 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 drm_i915_gem_object *obj; + unsigned old_width; + uint32_t addr; + int ret; + + /* if we want to turn off the cursor ignore width and height */ + if (!handle) { + DRM_DEBUG_KMS("cursor off\n"); + addr = 0; + obj = NULL; + mutex_lock(&dev->struct_mutex); + goto finish; + } + + /* Check for which cursor types we support */ + if (!((width == 64 && height == 64) || + (width == 128 && height == 128 && !IS_GEN2(dev)) || + (width == 256 && height == 256 && !IS_GEN2(dev)))) { + DRM_DEBUG("Cursor dimension not supported\n"); + return -EINVAL; + } + + obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); + if (&obj->base == NULL) + return -ENOENT; + + if (obj->base.size < width * height * 4) { + DRM_DEBUG_KMS("buffer is to small\n"); + ret = -ENOMEM; + goto fail; + } + + /* we only need to pin inside GTT if cursor is non-phy */ + mutex_lock(&dev->struct_mutex); + if (!INTEL_INFO(dev)->cursor_needs_physical) { + unsigned alignment; + + if (obj->tiling_mode) { + DRM_DEBUG_KMS("cursor cannot be tiled\n"); + ret = -EINVAL; + goto fail_locked; + } + + /* Note that the w/a also requires 2 PTE of padding following + * the bo. We currently fill all unused PTE with the shadow + * page and so we should always have valid PTE following the + * cursor preventing the VT-d warning. + */ + alignment = 0; + if (need_vtd_wa(dev)) + alignment = 64*1024; + + ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL); + if (ret) { + DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n"); + goto fail_locked; + } + + ret = i915_gem_object_put_fence(obj); + if (ret) { + DRM_DEBUG_KMS("failed to release fence for cursor"); + goto fail_unpin; + } + + addr = i915_gem_obj_ggtt_offset(obj); + } else { + int align = IS_I830(dev) ? 16 * 1024 : 256; + ret = i915_gem_attach_phys_object(dev, obj, + (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1, + align); + if (ret) { + DRM_DEBUG_KMS("failed to attach phys object\n"); + goto fail_locked; + } + addr = obj->phys_obj->handle->busaddr; + } + + if (IS_GEN2(dev)) + I915_WRITE(CURSIZE, (height << 12) | width); + + finish: + if (intel_crtc->cursor_bo) { + if (INTEL_INFO(dev)->cursor_needs_physical) { + if (intel_crtc->cursor_bo != obj) + i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); + } else + i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); + drm_gem_object_unreference(&intel_crtc->cursor_bo->base); + } + + mutex_unlock(&dev->struct_mutex); + + old_width = intel_crtc->cursor_width; + + intel_crtc->cursor_addr = addr; + intel_crtc->cursor_bo = obj; + intel_crtc->cursor_width = width; + intel_crtc->cursor_height = height; + + if (intel_crtc->active) { + if (old_width != width) + intel_update_watermarks(crtc); + intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); + } + + return 0; +fail_unpin: + i915_gem_object_unpin_from_display_plane(obj); +fail_locked: + mutex_unlock(&dev->struct_mutex); +fail: + drm_gem_object_unreference_unlocked(&obj->base); + return ret; +} + +int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX); + intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX); + + if (intel_crtc->active) + intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); + + return 0; +} diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9175cfc..d327735 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -42,7 +42,6 @@ #include static void intel_increase_pllclock(struct drm_crtc *crtc); -static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); static void i9xx_crtc_clock_get(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config); @@ -910,11 +909,6 @@ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, return I915_READ(SDEISR) & bit; } -static const char *state_string(bool enabled) -{ - return enabled ? "on" : "off"; -} - /* Only for pre-ILK configs */ void assert_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) @@ -1089,26 +1083,6 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv, pipe_name(pipe)); } -static void assert_cursor(struct drm_i915_private *dev_priv, - enum pipe pipe, bool state) -{ - struct drm_device *dev = dev_priv->dev; - bool cur_state; - - if (IS_845G(dev) || IS_I865G(dev)) - cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE; - else if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) - cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; - else - cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE; - - WARN(cur_state != state, - "cursor on pipe %c assertion failure (expected %s, current %s)\n", - pipe_name(pipe), state_string(state), state_string(cur_state)); -} -#define assert_cursor_enabled(d, p) assert_cursor(d, p, true) -#define assert_cursor_disabled(d, p) assert_cursor(d, p, false) - void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { @@ -1934,7 +1908,7 @@ static void intel_disable_primary_hw_plane(struct drm_i915_private *dev_priv, intel_wait_for_vblank(dev_priv->dev, pipe); } -static bool need_vtd_wa(struct drm_device *dev) +bool need_vtd_wa(struct drm_device *dev) { #ifdef CONFIG_INTEL_IOMMU if (INTEL_INFO(dev)->gen >= 6 && intel_iommu_gfx_mapped) @@ -7245,318 +7219,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return 0; } -static void i845_update_cursor(struct drm_crtc *crtc, u32 base) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - bool visible = base != 0; - u32 cntl; - - if (intel_crtc->cursor_visible == visible) - return; - - cntl = I915_READ(_CURACNTR); - if (visible) { - /* On these chipsets we can only modify the base whilst - * the cursor is disabled. - */ - I915_WRITE(_CURABASE, base); - - cntl &= ~(CURSOR_FORMAT_MASK); - /* XXX width must be 64, stride 256 => 0x00 << 28 */ - cntl |= CURSOR_ENABLE | - CURSOR_GAMMA_ENABLE | - CURSOR_FORMAT_ARGB; - } else - cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE); - I915_WRITE(_CURACNTR, cntl); - - intel_crtc->cursor_visible = visible; -} - -static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - bool visible = base != 0; - - if (intel_crtc->cursor_visible != visible) { - int16_t width = intel_crtc->cursor_width; - uint32_t cntl = I915_READ(CURCNTR(pipe)); - if (base) { - cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); - cntl |= MCURSOR_GAMMA_ENABLE; - - switch (width) { - case 64: - cntl |= CURSOR_MODE_64_ARGB_AX; - break; - case 128: - cntl |= CURSOR_MODE_128_ARGB_AX; - break; - case 256: - cntl |= CURSOR_MODE_256_ARGB_AX; - break; - default: - WARN_ON(1); - return; - } - cntl |= pipe << 28; /* Connect to correct pipe */ - } else { - cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); - cntl |= CURSOR_MODE_DISABLE; - } - I915_WRITE(CURCNTR(pipe), cntl); - - intel_crtc->cursor_visible = visible; - } - /* and commit changes on next vblank */ - POSTING_READ(CURCNTR(pipe)); - I915_WRITE(CURBASE(pipe), base); - POSTING_READ(CURBASE(pipe)); -} - -static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - bool visible = base != 0; - - if (intel_crtc->cursor_visible != visible) { - int16_t width = intel_crtc->cursor_width; - uint32_t cntl = I915_READ(CURCNTR_IVB(pipe)); - if (base) { - cntl &= ~CURSOR_MODE; - cntl |= MCURSOR_GAMMA_ENABLE; - switch (width) { - case 64: - cntl |= CURSOR_MODE_64_ARGB_AX; - break; - case 128: - cntl |= CURSOR_MODE_128_ARGB_AX; - break; - case 256: - cntl |= CURSOR_MODE_256_ARGB_AX; - break; - default: - WARN_ON(1); - return; - } - } else { - cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE); - cntl |= CURSOR_MODE_DISABLE; - } - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { - cntl |= CURSOR_PIPE_CSC_ENABLE; - cntl &= ~CURSOR_TRICKLE_FEED_DISABLE; - } - I915_WRITE(CURCNTR_IVB(pipe), cntl); - - intel_crtc->cursor_visible = visible; - } - /* and commit changes on next vblank */ - POSTING_READ(CURCNTR_IVB(pipe)); - I915_WRITE(CURBASE_IVB(pipe), base); - POSTING_READ(CURBASE_IVB(pipe)); -} - -/* 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, - bool on) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - int x = intel_crtc->cursor_x; - int y = intel_crtc->cursor_y; - u32 base = 0, pos = 0; - bool visible; - - if (on) - base = intel_crtc->cursor_addr; - - if (x >= intel_crtc->config.pipe_src_w) - base = 0; - - if (y >= intel_crtc->config.pipe_src_h) - base = 0; - - if (x < 0) { - if (x + intel_crtc->cursor_width <= 0) - base = 0; - - pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT; - x = -x; - } - pos |= x << CURSOR_X_SHIFT; - - if (y < 0) { - if (y + intel_crtc->cursor_height <= 0) - base = 0; - - pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT; - y = -y; - } - pos |= y << CURSOR_Y_SHIFT; - - visible = base != 0; - if (!visible && !intel_crtc->cursor_visible) - return; - - if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) { - I915_WRITE(CURPOS_IVB(pipe), pos); - ivb_update_cursor(crtc, base); - } else { - I915_WRITE(CURPOS(pipe), pos); - if (IS_845G(dev) || IS_I865G(dev)) - i845_update_cursor(crtc, base); - else - i9xx_update_cursor(crtc, base); - } -} - -static int intel_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_file *file, - uint32_t handle, - uint32_t width, uint32_t height) -{ - 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 drm_i915_gem_object *obj; - unsigned old_width; - uint32_t addr; - int ret; - - /* if we want to turn off the cursor ignore width and height */ - if (!handle) { - DRM_DEBUG_KMS("cursor off\n"); - addr = 0; - obj = NULL; - mutex_lock(&dev->struct_mutex); - goto finish; - } - - /* Check for which cursor types we support */ - if (!((width == 64 && height == 64) || - (width == 128 && height == 128 && !IS_GEN2(dev)) || - (width == 256 && height == 256 && !IS_GEN2(dev)))) { - DRM_DEBUG("Cursor dimension not supported\n"); - return -EINVAL; - } - - obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); - if (&obj->base == NULL) - return -ENOENT; - - if (obj->base.size < width * height * 4) { - DRM_DEBUG_KMS("buffer is to small\n"); - ret = -ENOMEM; - goto fail; - } - - /* we only need to pin inside GTT if cursor is non-phy */ - mutex_lock(&dev->struct_mutex); - if (!INTEL_INFO(dev)->cursor_needs_physical) { - unsigned alignment; - - if (obj->tiling_mode) { - DRM_DEBUG_KMS("cursor cannot be tiled\n"); - ret = -EINVAL; - goto fail_locked; - } - - /* Note that the w/a also requires 2 PTE of padding following - * the bo. We currently fill all unused PTE with the shadow - * page and so we should always have valid PTE following the - * cursor preventing the VT-d warning. - */ - alignment = 0; - if (need_vtd_wa(dev)) - alignment = 64*1024; - - ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL); - if (ret) { - DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n"); - goto fail_locked; - } - - ret = i915_gem_object_put_fence(obj); - if (ret) { - DRM_DEBUG_KMS("failed to release fence for cursor"); - goto fail_unpin; - } - - addr = i915_gem_obj_ggtt_offset(obj); - } else { - int align = IS_I830(dev) ? 16 * 1024 : 256; - ret = i915_gem_attach_phys_object(dev, obj, - (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1, - align); - if (ret) { - DRM_DEBUG_KMS("failed to attach phys object\n"); - goto fail_locked; - } - addr = obj->phys_obj->handle->busaddr; - } - - if (IS_GEN2(dev)) - I915_WRITE(CURSIZE, (height << 12) | width); - - finish: - if (intel_crtc->cursor_bo) { - if (INTEL_INFO(dev)->cursor_needs_physical) { - if (intel_crtc->cursor_bo != obj) - i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); - } else - i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); - drm_gem_object_unreference(&intel_crtc->cursor_bo->base); - } - - mutex_unlock(&dev->struct_mutex); - - old_width = intel_crtc->cursor_width; - - intel_crtc->cursor_addr = addr; - intel_crtc->cursor_bo = obj; - intel_crtc->cursor_width = width; - intel_crtc->cursor_height = height; - - if (intel_crtc->active) { - if (old_width != width) - intel_update_watermarks(crtc); - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); - } - - return 0; -fail_unpin: - i915_gem_object_unpin_from_display_plane(obj); -fail_locked: - mutex_unlock(&dev->struct_mutex); -fail: - drm_gem_object_unreference_unlocked(&obj->base); - return ret; -} - -static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX); - intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX); - - if (intel_crtc->active) - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); - - return 0; -} - static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7933fe2..914dcbc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -617,6 +617,10 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi) return container_of(intel_hdmi, struct intel_digital_port, hdmi); } +static inline const char *state_string(bool enabled) +{ + return enabled ? "on" : "off"; +} /* i915_irq.c */ bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, @@ -638,6 +642,19 @@ void intel_runtime_pm_restore_interrupts(struct drm_device *dev); void intel_crt_init(struct drm_device *dev); +/* intel_cursor.c */ +void assert_cursor(struct drm_i915_private *dev_priv, enum pipe pipe, + bool state); +#define assert_cursor_enabled(d, p) assert_cursor(d, p, true) +#define assert_cursor_disabled(d, p) assert_cursor(d, p, false) +void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on); +int intel_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file, + uint32_t handle, + uint32_t width, uint32_t height); +int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); + + /* intel_ddi.c */ void intel_prepare_ddi(struct drm_device *dev); void hsw_fdi_link_train(struct drm_crtc *crtc); @@ -752,6 +769,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode, struct intel_crtc_config *pipe_config); int intel_format_to_fourcc(int format); bool intel_pipe_has_type(struct drm_crtc *crtc, int type); +bool need_vtd_wa(struct drm_device *dev); /* intel_dp.c */ void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);