mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-03 23:58:05 +00:00
drm/i915/vblank: add and use intel_de_read64_2x32() to read vblank counter
Add intel_de_read64_2x32() wrapper for the uncore version of the same, and use it to read the high and low frame registers. Avoid duplicating code for existing helpers. The slight functional difference is checking that the entire high register remains the same across two reads, instead of just the part we're interested in. This should be of no consequence. (Unless those bits function as a PRNG.) Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/33853549adff82045b95af527e14cfdff5712470.1673873708.git.jani.nikula@intel.com
This commit is contained in:
parent
75018f47ac
commit
1af13bc6d0
2 changed files with 13 additions and 19 deletions
|
@ -22,6 +22,13 @@ intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg)
|
||||||
return intel_uncore_read8(&i915->uncore, reg);
|
return intel_uncore_read8(&i915->uncore, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u64
|
||||||
|
intel_de_read64_2x32(struct drm_i915_private *i915,
|
||||||
|
i915_reg_t lower_reg, i915_reg_t upper_reg)
|
||||||
|
{
|
||||||
|
return intel_uncore_read64_2x32(&i915->uncore, lower_reg, upper_reg);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg)
|
intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,9 +68,8 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc)
|
||||||
struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)];
|
struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)];
|
||||||
const struct drm_display_mode *mode = &vblank->hwmode;
|
const struct drm_display_mode *mode = &vblank->hwmode;
|
||||||
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
enum pipe pipe = to_intel_crtc(crtc)->pipe;
|
||||||
i915_reg_t high_frame, low_frame;
|
u32 pixel, vbl_start, hsync_start, htotal;
|
||||||
u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal;
|
u64 frame;
|
||||||
unsigned long irqflags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On i965gm TV output the frame counter only works up to
|
* On i965gm TV output the frame counter only works up to
|
||||||
|
@ -98,34 +97,22 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc)
|
||||||
/* Start of vblank event occurs at start of hsync */
|
/* Start of vblank event occurs at start of hsync */
|
||||||
vbl_start -= htotal - hsync_start;
|
vbl_start -= htotal - hsync_start;
|
||||||
|
|
||||||
high_frame = PIPEFRAME(pipe);
|
|
||||||
low_frame = PIPEFRAMEPIXEL(pipe);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* High & low register fields aren't synchronized, so make sure
|
* High & low register fields aren't synchronized, so make sure
|
||||||
* we get a low value that's stable across two reads of the high
|
* we get a low value that's stable across two reads of the high
|
||||||
* register.
|
* register.
|
||||||
*/
|
*/
|
||||||
do {
|
frame = intel_de_read64_2x32(dev_priv, PIPEFRAMEPIXEL(pipe), PIPEFRAME(pipe));
|
||||||
high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK;
|
|
||||||
low = intel_de_read_fw(dev_priv, low_frame);
|
|
||||||
high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK;
|
|
||||||
} while (high1 != high2);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
pixel = frame & PIPE_PIXEL_MASK;
|
||||||
|
frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff;
|
||||||
high1 >>= PIPE_FRAME_HIGH_SHIFT;
|
|
||||||
pixel = low & PIPE_PIXEL_MASK;
|
|
||||||
low >>= PIPE_FRAME_LOW_SHIFT;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The frame counter increments at beginning of active.
|
* The frame counter increments at beginning of active.
|
||||||
* Cook up a vblank counter by also checking the pixel
|
* Cook up a vblank counter by also checking the pixel
|
||||||
* counter against vblank start.
|
* counter against vblank start.
|
||||||
*/
|
*/
|
||||||
return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
|
return (frame + (pixel >= vbl_start)) & 0xffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 g4x_get_vblank_counter(struct drm_crtc *crtc)
|
u32 g4x_get_vblank_counter(struct drm_crtc *crtc)
|
||||||
|
|
Loading…
Reference in a new issue