From patchwork Thu Dec 30 21:16:29 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 440871 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oBUMZ9Hb016878 for ; Thu, 30 Dec 2010 22:35:30 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9BB599E7D1 for ; Thu, 30 Dec 2010 13:17:58 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from oproxy2-pub.bluehost.com (oproxy2-pub.bluehost.com [67.222.39.60]) by gabe.freedesktop.org (Postfix) with SMTP id 63F1B9E747 for ; Thu, 30 Dec 2010 13:16:48 -0800 (PST) Received: (qmail 13550 invoked by uid 0); 30 Dec 2010 21:16:47 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by oproxy2.bluehost.com with SMTP; 30 Dec 2010 21:16:47 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=virtuousgeek.org; h=Received:From:To:Cc:Subject:Date:Message-Id:X-Mailer:In-Reply-To:References:X-Identified-User; b=F4SsSfDzAraXLGEuXHM+pJ93qp77KawE8T7fiLL3lVOLvhUbagnocbA70JZtcIw43oLKXeR3xjjE53S2aiF2pfwoIKgjGHB0r4gcy/1UX7SlnTlYGTWFF1QJoVpThxjT; Received: from c-67-174-193-198.hsd1.ca.comcast.net ([67.174.193.198] helo=localhost.localdomain) by box514.bluehost.com with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.69) (envelope-from ) id 1PYPra-0006p7-Fn; Thu, 30 Dec 2010 14:16:46 -0700 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Date: Thu, 30 Dec 2010 13:16:29 -0800 Message-Id: <1293743792-8665-2-git-send-email-jbarnes@virtuousgeek.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1293743792-8665-1-git-send-email-jbarnes@virtuousgeek.org> References: <1293743792-8665-1-git-send-email-jbarnes@virtuousgeek.org> X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 67.174.193.198 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH 1/4] drm/i915: add pipe enable/disable functions X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 30 Dec 2010 22:35:30 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6313076..559e342 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1058,6 +1058,136 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) } } +enum state { + off = 0, + on = 1, +}; + +static char *state_string(enum state enabled) +{ + return (enabled ? "on" : "off"); +} + +/* Only for pre-ILK configs */ +static void assert_pll(struct drm_i915_private *dev_priv, enum pipe pipe, + enum state state) +{ + int reg; + u32 val; + bool cur_state; + + reg = DPLL(pipe); + val = I915_READ(reg); + cur_state = !!(val & DPLL_VCO_ENABLE); + WARN(cur_state != state, + "PLL state assertion failure (expected %s, current %s)\n", + state_string(state), state_string(cur_state)); +} +#define assert_pll_enabled(d, p) assert_pll(d, p, on) +#define assert_pll_disabled(d, p) assert_pll(d, p, off) + +static void assert_plane_enabled(struct drm_i915_private *dev_priv, + enum plane plane) +{ + int reg; + u32 val; + + reg = DSPCNTR(plane); + val = I915_READ(reg); + WARN(!(val & DISPLAY_PLANE_ENABLE), + "plane %c assertion failure, should be active but is disabled\n", + plane ? 'B' : 'A'); +} + +static void assert_planes_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + int reg, i; + u32 val; + int cur_pipe; + + /* Need to check both planes against the pipe */ + for (i = 0; i < 2; i++) { + reg = DSPCNTR(i); + val = I915_READ(reg); + cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> + DISPPLANE_SEL_PIPE_SHIFT; + WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, + "plane %d assertion failure, should be off on pipe %c but is still active\n", + i, pipe ? 'B' : 'A'); + } +} + +/** + * intel_enable_pipe - enable a pipe, assertiing requirements + * @dev_priv: i915 private structure + * @pipe: pipe to enable + * + * Enable @pipe, making sure that various hardware specific requirements + * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc. + * + * @pipe should be %PIPE_A or %PIPE_B. + * + * Will wait until the pipe is actually running (i.e. first vblank) before + * returning. + */ +static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) +{ + int reg; + u32 val; + + /* + * A pipe without a PLL won't actually be able to drive bits from + * a plane. On ILK+ the pipe PLLs are integrated, so we don't + * need the check. + */ + if (!HAS_PCH_SPLIT(dev_priv->dev)) + assert_pll_enabled(dev_priv, pipe); + + reg = PIPECONF(pipe); + val = I915_READ(reg); + val |= PIPECONF_ENABLE; + I915_WRITE(reg, val); + POSTING_READ(reg); + intel_wait_for_vblank(dev_priv->dev, pipe); +} + +/** + * intel_disable_pipe - disable a pipe, assertiing requirements + * @dev_priv: i915 private structure + * @pipe: pipe to disable + * + * Disable @pipe, making sure that various hardware specific requirements + * are met, if applicable, e.g. plane disabled, panel fitter off, etc. + * + * @pipe should be %PIPE_A or %PIPE_B. + * + * Will wait until the pipe has shut down before returning. + */ +static void intel_disable_pipe(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + int reg; + u32 val; + + /* + * Make sure planes won't keep trying to pump pixels to us, + * or we might hang the display. + */ + assert_planes_disabled(dev_priv, pipe); + + /* Don't disable pipe A or pipe A PLLs if needed */ + if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) + return; + + reg = PIPECONF(pipe); + val = I915_READ(reg); + val &= ~PIPECONF_ENABLE; + I915_WRITE(reg, val); + POSTING_READ(reg); + intel_wait_for_pipe_off(dev_priv->dev, pipe); +} + static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) { struct drm_device *dev = crtc->dev; @@ -2062,14 +2192,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) dev_priv->pch_pf_size); } - /* Enable CPU pipe */ - reg = PIPECONF(pipe); - temp = I915_READ(reg); - if ((temp & PIPECONF_ENABLE) == 0) { - I915_WRITE(reg, temp | PIPECONF_ENABLE); - POSTING_READ(reg); - intel_wait_for_vblank(dev, intel_crtc->pipe); - } + intel_enable_pipe(dev_priv, pipe); /* configure and enable CPU plane */ reg = DSPCNTR(plane); @@ -2197,15 +2320,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) dev_priv->display.disable_fbc) dev_priv->display.disable_fbc(dev); - /* disable cpu pipe, disable after all planes disabled */ - reg = PIPECONF(pipe); - temp = I915_READ(reg); - if (temp & PIPECONF_ENABLE) { - I915_WRITE(reg, temp & ~PIPECONF_ENABLE); - POSTING_READ(reg); - /* wait for cpu pipe off, pipe state */ - intel_wait_for_pipe_off(dev, intel_crtc->pipe); - } + intel_disable_pipe(dev_priv, pipe); if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || HAS_eDP) I915_WRITE(PCH_DP_D, I915_READ(PCH_DP_D) & ~DP_PORT_EN); @@ -2403,11 +2518,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) udelay(150); } - /* Enable the pipe */ - reg = PIPECONF(pipe); - temp = I915_READ(reg); - if ((temp & PIPECONF_ENABLE) == 0) - I915_WRITE(reg, temp | PIPECONF_ENABLE); + intel_enable_pipe(dev_priv, pipe); /* Enable the plane */ reg = DSPCNTR(plane); @@ -2464,16 +2575,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) goto done; - /* Next, disable display pipes */ - reg = PIPECONF(pipe); - temp = I915_READ(reg); - if (temp & PIPECONF_ENABLE) { - I915_WRITE(reg, temp & ~PIPECONF_ENABLE); - - /* Wait for the pipe to turn off */ - POSTING_READ(reg); - intel_wait_for_pipe_off(dev, pipe); - } + intel_disable_pipe(dev_priv, pipe); reg = DPLL(pipe); temp = I915_READ(reg); @@ -4215,7 +4317,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, if (!HAS_PCH_SPLIT(dev)) { dspcntr |= DISPLAY_PLANE_ENABLE; - pipeconf |= PIPECONF_ENABLE; dpll |= DPLL_VCO_ENABLE; } @@ -4426,6 +4527,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(PIPECONF(pipe), pipeconf); POSTING_READ(PIPECONF(pipe)); + if (!HAS_PCH_SPLIT(dev)) + intel_enable_pipe(dev_priv, pipe); intel_wait_for_vblank(dev, pipe); @@ -5579,16 +5682,7 @@ static void intel_sanitize_modesetting(struct drm_device *dev, if (IS_GEN2(dev)) intel_wait_for_vblank(dev, pipe); - if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) - return; - - /* Switch off the pipe. */ - reg = PIPECONF(pipe); - val = I915_READ(reg); - if (val & PIPECONF_ENABLE) { - I915_WRITE(reg, val & ~PIPECONF_ENABLE); - intel_wait_for_pipe_off(dev, pipe); - } + intel_disable_pipe(dev_priv, pipe); } static void intel_crtc_init(struct drm_device *dev, int pipe)