drm/i915: Fix pre-CTG vblank counter
The old style frame counter increments at the start of active video. However for i915_get_vblank_counter() we want a counter that increments at the start of vblank. Fortunately the low frame counter register also contains the pixel counter for the current frame. We can can compare that against the vblank start pixel count to determine if we need to increment the frame counter by 1 to get the correct answer. Also reorganize the function pointer assignments in intel_irq_init() a bit to avoid confusing people. Cc: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
0632fef669
commit
391f75e2bf
|
@ -526,7 +526,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
|
|||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long high_frame;
|
||||
unsigned long low_frame;
|
||||
u32 high1, high2, low;
|
||||
u32 high1, high2, low, pixel, vbl_start;
|
||||
|
||||
if (!i915_pipe_enabled(dev, pipe)) {
|
||||
DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
|
||||
|
@ -534,6 +534,24 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct intel_crtc *intel_crtc =
|
||||
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
||||
const struct drm_display_mode *mode =
|
||||
&intel_crtc->config.adjusted_mode;
|
||||
|
||||
vbl_start = mode->crtc_vblank_start * mode->crtc_htotal;
|
||||
} else {
|
||||
enum transcoder cpu_transcoder =
|
||||
intel_pipe_to_cpu_transcoder(dev_priv, pipe);
|
||||
u32 htotal;
|
||||
|
||||
htotal = ((I915_READ(HTOTAL(cpu_transcoder)) >> 16) & 0x1fff) + 1;
|
||||
vbl_start = (I915_READ(VBLANK(cpu_transcoder)) & 0x1fff) + 1;
|
||||
|
||||
vbl_start *= htotal;
|
||||
}
|
||||
|
||||
high_frame = PIPEFRAME(pipe);
|
||||
low_frame = PIPEFRAMEPIXEL(pipe);
|
||||
|
||||
|
@ -544,13 +562,20 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
|
|||
*/
|
||||
do {
|
||||
high1 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
|
||||
low = I915_READ(low_frame) & PIPE_FRAME_LOW_MASK;
|
||||
low = I915_READ(low_frame);
|
||||
high2 = I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK;
|
||||
} while (high1 != high2);
|
||||
|
||||
high1 >>= PIPE_FRAME_HIGH_SHIFT;
|
||||
pixel = low & PIPE_PIXEL_MASK;
|
||||
low >>= PIPE_FRAME_LOW_SHIFT;
|
||||
return (high1 << 8) | low;
|
||||
|
||||
/*
|
||||
* The frame counter increments at beginning of active.
|
||||
* Cook up a vblank counter by also checking the pixel
|
||||
* counter against vblank start.
|
||||
*/
|
||||
return ((high1 << 8) | low) + (pixel >= vbl_start);
|
||||
}
|
||||
|
||||
static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
|
||||
|
@ -3155,11 +3180,12 @@ void intel_irq_init(struct drm_device *dev)
|
|||
|
||||
pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
dev->driver->get_vblank_counter = i915_get_vblank_counter;
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
|
||||
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
|
||||
dev->driver->get_vblank_counter = gm45_get_vblank_counter;
|
||||
} else {
|
||||
dev->driver->get_vblank_counter = i915_get_vblank_counter;
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
|
|
Loading…
Reference in New Issue