Skip to content

Commit

Permalink
drm/i915: workaround bad DSL readout v3
Browse files Browse the repository at this point in the history
On HSW at least (still testing other platforms, but should be harmless
elsewhere), the DSL reg reads back as 0 when read around vblank start
time.  This ends up confusing the atomic start/end checking code, since
it causes the update to appear as if it crossed a frame count boundary.
Avoid the problem by making sure we don't return scanline_offset from
the get_crtc_scanline function.  In moving the code there, I add to add
an additional delay since it could be called and have a legitimate 0
result for some time (depending on the pixel clock).

v2: move hsw dsl read hack to get_crtc_scanline (Ville)
v3: use break instead of goto (Ville)
    update comment with workaround details (Ville)

References: https://bugs.freedesktop.org/show_bug.cgi?id=91579
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
  • Loading branch information
Jesse Barnes authored and Jani Nikula committed Sep 23, 2015
1 parent 95d0be6 commit 41b578f
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,32 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
else
position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;

/*
* On HSW, the DSL reg (0x70000) appears to return 0 if we
* read it just before the start of vblank. So try it again
* so we don't accidentally end up spanning a vblank frame
* increment, causing the pipe_update_end() code to squak at us.
*
* The nature of this problem means we can't simply check the ISR
* bit and return the vblank start value; nor can we use the scanline
* debug register in the transcoder as it appears to have the same
* problem. We may need to extend this to include other platforms,
* but so far testing only shows the problem on HSW.
*/
if (IS_HASWELL(dev) && !position) {
int i, temp;

for (i = 0; i < 100; i++) {
udelay(1);
temp = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) &
DSL_LINEMASK_GEN3;
if (temp != position) {
position = temp;
break;
}
}
}

/*
* See update_scanline_offset() for the details on the
* scanline_offset adjustment.
Expand Down

0 comments on commit 41b578f

Please sign in to comment.