Skip to content

Commit

Permalink
drm/i915: Use pipe state to tell when pipe is off
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Keith Packard authored and Chris Wilson committed Oct 3, 2010
1 parent b99a9d9 commit ab7ad7f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 25 deletions.
62 changes: 38 additions & 24 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,34 +1013,48 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
DRM_DEBUG_KMS("vblank wait timed out\n");
}

/**
* intel_wait_for_vblank_off - wait for vblank after disabling a pipe
/*
* intel_wait_for_pipe_off - wait for pipe to turn off
* @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).
* On Gen4 and above:
* wait for the pipe register state bit to turn off
*
* Otherwise:
* wait 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)
static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
{
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");

if (INTEL_INFO(dev)->gen >= 4) {
int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF);

/* Wait for the Pipe State to go off */
if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0,
100, 0))
DRM_DEBUG_KMS("pipe_off wait timed out\n");
} else {
u32 last_line;
int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL);
unsigned long timeout = jiffies + msecs_to_jiffies(100);

/* 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("pipe_off wait timed out\n");
}
}

/* Parameters have changed, update FBC info */
Expand Down Expand Up @@ -2328,13 +2342,13 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_READ(dspbase_reg);
}

/* 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 &&
(dev_priv->quirks & QUIRK_PIPEA_FORCE))
(dev_priv->quirks & QUIRK_PIPEA_FORCE)) {
/* Wait for vblank for the disable to take effect */
intel_wait_for_vblank(dev, pipe);
goto skip_pipe_off;
}

/* Next, disable display pipes */
temp = I915_READ(pipeconf_reg);
Expand All @@ -2343,8 +2357,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
I915_READ(pipeconf_reg);
}

/* Wait for vblank for the disable to take effect. */
intel_wait_for_vblank_off(dev, pipe);
/* Wait for the pipe to turn off */
intel_wait_for_pipe_off(dev, pipe);

temp = I915_READ(dpll_reg);
if ((temp & DPLL_VCO_ENABLE) != 0) {
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,6 @@ 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_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,
Expand Down

0 comments on commit ab7ad7f

Please sign in to comment.