aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2010-10-03 03:33:06 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-03 05:23:26 -0400
commitab7ad7f6451580aa7eccc0ba62807c872088a8f9 (patch)
tree3db4739a40c0276e2c8ee99a9465317360769e90 /drivers/gpu/drm/i915/intel_display.c
parentb99a9d9bb62a984bdfcb6c973dfe180bd776abbe (diff)
drm/i915: Use pipe state to tell when pipe is off
Instead of waiting for the display line value to settle, we can simply wait for the pipe configuration register 'state' bit to turn off. Contrarywise, disabling the plane will not cause the display line value to stop changing, so instead we wait for the vblank interrupt bit to get set. And, we only do this when we're not about to wait for the pipe to turn off. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b5bf51a4502d..979228594599 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1013,8 +1013,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
1013 DRM_DEBUG_KMS("vblank wait timed out\n"); 1013 DRM_DEBUG_KMS("vblank wait timed out\n");
1014} 1014}
1015 1015
1016/** 1016/*
1017 * intel_wait_for_vblank_off - wait for vblank after disabling a pipe 1017 * intel_wait_for_pipe_off - wait for pipe to turn off
1018 * @dev: drm device 1018 * @dev: drm device
1019 * @pipe: pipe to wait for 1019 * @pipe: pipe to wait for
1020 * 1020 *
@@ -1022,25 +1022,39 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
1022 * spinning on the vblank interrupt status bit, since we won't actually 1022 * spinning on the vblank interrupt status bit, since we won't actually
1023 * see an interrupt when the pipe is disabled. 1023 * see an interrupt when the pipe is disabled.
1024 * 1024 *
1025 * So this function waits for the display line value to settle (it 1025 * On Gen4 and above:
1026 * usually ends up stopping at the start of the next frame). 1026 * wait for the pipe register state bit to turn off
1027 *
1028 * Otherwise:
1029 * wait for the display line value to settle (it usually
1030 * ends up stopping at the start of the next frame).
1031 *
1027 */ 1032 */
1028void intel_wait_for_vblank_off(struct drm_device *dev, int pipe) 1033static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
1029{ 1034{
1030 struct drm_i915_private *dev_priv = dev->dev_private; 1035 struct drm_i915_private *dev_priv = dev->dev_private;
1031 int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); 1036
1032 unsigned long timeout = jiffies + msecs_to_jiffies(100); 1037 if (INTEL_INFO(dev)->gen >= 4) {
1033 u32 last_line; 1038 int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF);
1034 1039
1035 /* Wait for the display line to settle */ 1040 /* Wait for the Pipe State to go off */
1036 do { 1041 if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0,
1037 last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; 1042 100, 0))
1038 mdelay(5); 1043 DRM_DEBUG_KMS("pipe_off wait timed out\n");
1039 } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && 1044 } else {
1040 time_after(timeout, jiffies)); 1045 u32 last_line;
1041 1046 int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
1042 if (time_after(jiffies, timeout)) 1047 unsigned long timeout = jiffies + msecs_to_jiffies(100);
1043 DRM_DEBUG_KMS("vblank wait timed out\n"); 1048
1049 /* Wait for the display line to settle */
1050 do {
1051 last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK;
1052 mdelay(5);
1053 } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) &&
1054 time_after(timeout, jiffies));
1055 if (time_after(jiffies, timeout))
1056 DRM_DEBUG_KMS("pipe_off wait timed out\n");
1057 }
1044} 1058}
1045 1059
1046/* Parameters have changed, update FBC info */ 1060/* Parameters have changed, update FBC info */
@@ -2328,13 +2342,13 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
2328 I915_READ(dspbase_reg); 2342 I915_READ(dspbase_reg);
2329 } 2343 }
2330 2344
2331 /* Wait for vblank for the disable to take effect */
2332 intel_wait_for_vblank_off(dev, pipe);
2333
2334 /* Don't disable pipe A or pipe A PLLs if needed */ 2345 /* Don't disable pipe A or pipe A PLLs if needed */
2335 if (pipeconf_reg == PIPEACONF && 2346 if (pipeconf_reg == PIPEACONF &&
2336 (dev_priv->quirks & QUIRK_PIPEA_FORCE)) 2347 (dev_priv->quirks & QUIRK_PIPEA_FORCE)) {
2348 /* Wait for vblank for the disable to take effect */
2349 intel_wait_for_vblank(dev, pipe);
2337 goto skip_pipe_off; 2350 goto skip_pipe_off;
2351 }
2338 2352
2339 /* Next, disable display pipes */ 2353 /* Next, disable display pipes */
2340 temp = I915_READ(pipeconf_reg); 2354 temp = I915_READ(pipeconf_reg);
@@ -2343,8 +2357,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
2343 I915_READ(pipeconf_reg); 2357 I915_READ(pipeconf_reg);
2344 } 2358 }
2345 2359
2346 /* Wait for vblank for the disable to take effect. */ 2360 /* Wait for the pipe to turn off */
2347 intel_wait_for_vblank_off(dev, pipe); 2361 intel_wait_for_pipe_off(dev, pipe);
2348 2362
2349 temp = I915_READ(dpll_reg); 2363 temp = I915_READ(dpll_reg);
2350 if ((temp & DPLL_VCO_ENABLE) != 0) { 2364 if ((temp & DPLL_VCO_ENABLE) != 0) {