From patchwork Wed Aug 18 19:00:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 120235 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o7IJ5nLA020369 for ; Wed, 18 Aug 2010 19:06:25 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DDB029EF22 for ; Wed, 18 Aug 2010 12:05:49 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from cpoproxy3-pub.bluehost.com (cpoproxy3-pub.bluehost.com [67.222.54.6]) by gabe.freedesktop.org (Postfix) with SMTP id 4B00F9EF4F for ; Wed, 18 Aug 2010 12:01:21 -0700 (PDT) Received: (qmail 12738 invoked by uid 0); 18 Aug 2010 19:01:20 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by cpoproxy3.bluehost.com with SMTP; 18 Aug 2010 19:01:20 -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=kll45MK7FF4QTmq7bUBPyalIQHJywM/fghw3tItgvKU9+cYVVkae49A4pScR8jRFSC76TovoQOVN11R6IAIBeop54RdrjW7MXQ8/YJkHdA6e4bgJ89/YvI5I5WZ6UP6v; Received: from [75.110.194.140] (helo=localhost.localdomain) by box514.bluehost.com with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.69) (envelope-from ) id 1Olnsy-0002jG-TM; Wed, 18 Aug 2010 13:01:17 -0600 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Date: Wed, 18 Aug 2010 12:00:36 -0700 Message-Id: <1282158036-1671-8-git-send-email-jbarnes@virtuousgeek.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1282158036-1671-1-git-send-email-jbarnes@virtuousgeek.org> References: <1282158036-1671-1-git-send-email-jbarnes@virtuousgeek.org> X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 75.110.194.140 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH 7/7] drm/i915: wait for actual vblank, not just 20ms 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 (demeter.kernel.org [140.211.167.41]); Wed, 18 Aug 2010 19:06:25 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index cf41c67..822b21c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2080,6 +2080,7 @@ #define PIPE_DITHER_TYPE_ST01 (1 << 2) /* Pipe A */ #define PIPEADSL 0x70000 +#define DSL_LINEMASK 0x00000fff #define PIPEACONF 0x70008 #define PIPEACONF_ENABLE (1<<31) #define PIPEACONF_DISABLE 0 diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index ee0732b..4a2f593 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -331,7 +331,7 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); /* Wait for next Vblank to substitue * border color for Color info */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, pipe); st00 = I915_READ8(VGA_MSR_WRITE); status = ((st00 & (1 << 4)) != 0) ? connector_status_connected : diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 928bcc2..27e60b8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -972,11 +972,57 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, return true; } -void -intel_wait_for_vblank(struct drm_device *dev) +/** + * intel_wait_for_vblank - wait for vblank on a given pipe + * @dev: drm device + * @pipe: pipe to wait for + * + * Wait for vblank to occur on a given pipe. Needed for various bits of + * mode setting code. + */ +void intel_wait_for_vblank(struct drm_device *dev, int pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT); + unsigned long timeout = jiffies + msecs_to_jiffies(100); + + /* Wait for vblank interrupt bit to set */ + while (!(I915_READ(pipestat_reg) & PIPE_VBLANK_INTERRUPT_STATUS) && + time_after(timeout, jiffies)) + mdelay(1); + + if (time_after(jiffies, timeout)) + DRM_DEBUG_KMS("vblank wait timed out\n"); +} + +/** + * intel_wait_for_vblank_off - wait for vblank after disabling a pipe + * @dev: drm device + * @pipe: pipe to wait for + * + * After disabling a pipe, we can't wait for vblank in the usual way, + * spinning on the vblank interrupt status bit, since we won't actually + * see an interrupt when the pipe is disabled. + * + * So this function waits for the display line value to settle (it + * usually ends up stopping at the start of the next frame). + */ +void intel_wait_for_vblank_off(struct drm_device *dev, int pipe) { - /* Wait for 20ms, i.e. one cycle at 50hz. */ - msleep(20); + struct drm_i915_private *dev_priv = dev->dev_private; + int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); + unsigned long timeout = jiffies + msecs_to_jiffies(100); + u32 last_line; + + /* Wait for the display line to settle */ + do { + last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; + mdelay(5); + } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && + time_after(timeout, jiffies)); + + if (time_after(jiffies, timeout)) + DRM_DEBUG_KMS("vblank wait timed out\n"); } /* Parameters have changed, update FBC info */ @@ -1053,8 +1099,6 @@ void i8xx_disable_fbc(struct drm_device *dev) ; /* do nothing */ } - intel_wait_for_vblank(dev); - DRM_DEBUG_KMS("disabled FBC\n"); } @@ -1111,7 +1155,6 @@ void g4x_disable_fbc(struct drm_device *dev) dpfc_ctl = I915_READ(DPFC_CONTROL); dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(DPFC_CONTROL, dpfc_ctl); - intel_wait_for_vblank(dev); DRM_DEBUG_KMS("disabled FBC\n"); } @@ -1429,7 +1472,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, if ((IS_I965G(dev) || plane == 0)) intel_update_fbc(crtc, &crtc->mode); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, pipe); if (old_fb) { intel_fb = to_intel_framebuffer(old_fb); @@ -2205,10 +2248,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(dspbase_reg); } - if (!IS_I9XX(dev)) { - /* Wait for vblank for the disable to take effect */ - intel_wait_for_vblank(dev); - } + /* Wait for vblank for the disable to take effect */ + intel_wait_for_vblank_off(dev, pipe); /* Don't disable pipe A or pipe A PLLs if needed */ if (pipeconf_reg == PIPEACONF && @@ -2223,7 +2264,7 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) } /* Wait for vblank for the disable to take effect. */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank_off(dev, pipe); temp = I915_READ(dpll_reg); if ((temp & DPLL_VCO_ENABLE) != 0) { @@ -3828,7 +3869,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(pipeconf_reg, pipeconf); I915_READ(pipeconf_reg); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, pipe); if (IS_IRONLAKE(dev)) { /* enable address swizzle for tiling buffer */ @@ -4170,7 +4211,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, encoder_funcs->commit(encoder); } /* let the connector get through one full cycle before testing */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, intel_crtc->pipe); return crtc; } @@ -4375,7 +4416,7 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule) dpll &= ~DISPLAY_RATE_SELECT_FPA1; I915_WRITE(dpll_reg, dpll); dpll = I915_READ(dpll_reg); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, pipe); dpll = I915_READ(dpll_reg); if (dpll & DISPLAY_RATE_SELECT_FPA1) DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); @@ -4419,7 +4460,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc) dpll |= DISPLAY_RATE_SELECT_FPA1; I915_WRITE(dpll_reg, dpll); dpll = I915_READ(dpll_reg); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, pipe); dpll = I915_READ(dpll_reg); if (!(dpll & DISPLAY_RATE_SELECT_FPA1)) DRM_DEBUG_DRIVER("failed to downclock LVDS!\n"); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 87b7a49..e008587 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1120,12 +1120,13 @@ intel_dp_set_link_train(struct intel_encoder *intel_encoder, struct drm_device *dev = intel_encoder->enc.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dp_priv *dp_priv = intel_encoder->dev_priv; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->enc.crtc); int ret; I915_WRITE(dp_priv->output_reg, dp_reg_value); POSTING_READ(dp_priv->output_reg); if (first) - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, intel_crtc->pipe); intel_dp_aux_native_write_1(intel_encoder, DP_TRAINING_PATTERN_SET, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2f7970b..93340ed 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -193,7 +193,8 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc); int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void intel_wait_for_vblank(struct drm_device *dev); +extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe); +extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_connector *connector, diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 76993ac..353e400 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1275,6 +1275,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->enc.crtc); u32 temp; if (mode != DRM_MODE_DPMS_ON) { @@ -1297,7 +1298,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) if ((temp & SDVO_ENABLE) == 0) intel_sdvo_write_sdvox(intel_encoder, temp | SDVO_ENABLE); for (i = 0; i < 2; i++) - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, intel_crtc->pipe); status = intel_sdvo_get_trained_inputs(intel_encoder, &input1, &input2); diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 6d553c2..6651855 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1156,11 +1156,11 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, /* Wait for vblank for the disable to take effect */ if (!IS_I9XX(dev)) - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, intel_crtc->pipe); I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); /* Wait for vblank for the disable to take effect. */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, intel_crtc->pipe); /* Filter ctl must be set before TV_WIN_SIZE */ I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); @@ -1229,6 +1229,7 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder struct drm_encoder *encoder = &intel_encoder->enc; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->enc.crtc); unsigned long irqflags; u32 tv_ctl, save_tv_ctl; u32 tv_dac, save_tv_dac; @@ -1265,11 +1266,11 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder DAC_C_0_7_V); I915_WRITE(TV_CTL, tv_ctl); I915_WRITE(TV_DAC, tv_dac); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, intel_crtc->pipe); tv_dac = I915_READ(TV_DAC); I915_WRITE(TV_DAC, save_tv_dac); I915_WRITE(TV_CTL, save_tv_ctl); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(dev, intel_crtc->pipe); /* * A B C * 0 1 1 Composite