diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-05-09 17:03:28 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-05-10 11:21:31 +0300 |
commit | 1bf6ad622b9be58484279978f85716fbb10d545b (patch) | |
tree | f7add5183253140848bff995e5084e8fd35dacb8 /drivers/gpu/drm/i915/i915_irq.c | |
parent | 2a39b88bc121645e95a2b3b25a97ef4ceb4208b8 (diff) | |
download | linux-1bf6ad622b9be58484279978f85716fbb10d545b.tar.xz |
drm/vblank: drop the mode argument from drm_calc_vbltimestamp_from_scanoutpos
If we restrict this helper to only kms drivers (which is the case) we
can look up the correct mode easily ourselves. But it's a bit tricky:
- All legacy drivers look at crtc->hwmode. But that is updated already
at the beginning of the modeset helper, which means when we disable
a pipe. Hence the final timestamps might be a bit off. But since
this is an existing bug I'm not going to change it, but just try to
be bug-for-bug compatible with the current code. This only applies
to radeon&amdgpu.
- i915 tries to get it perfect by updating crtc->hwmode when the pipe
is off (i.e. vblank->enabled = false).
- All other atomic drivers look at crtc->state->adjusted_mode. Those
that look at state->requested_mode simply don't adjust their mode,
so it's the same. That has two problems: Accessing crtc->state from
interrupt handling code is unsafe, and it's updated before we shut
down the pipe. For nonblocking modesets it's even worse.
For atomic drivers try to implement what i915 does. To do that we add
a new hwmode field to the vblank structure, and update it from
drm_calc_timestamping_constants(). For atomic drivers that's called
from the right spot by the helper library already, so all fine. But
for safety let's enforce that.
For legacy driver this function is only called at the end (oh the
fun), which is broken, so again let's not bother and just stay
bug-for-bug compatible.
The benefit is that we can use drm_calc_vbltimestamp_from_scanoutpos
directly to implement ->get_vblank_timestamp in every driver, deleting
a lot of code.
v2: Completely new approach, trying to mimick the i915 solution.
v3: Fixup kerneldoc.
v4: Drop the WARN_ON to check that the vblank is off, atomic helpers
currently unconditionally call this. Recomputing the same stuff should
be harmless.
v5: Fix typos and move misplaced hunks to the right patches (Neil).
v6: Undo hunk movement (kbuild).
Cc: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Cc: Eric Anholt <eric@anholt.net>
Cc: Rob Clark <robdclark@gmail.com>
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170509140329.24114-4-daniel.vetter@ffwll.ch
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 52 |
1 files changed, 7 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ae09c29662a1..dccb7c2560fe 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -827,10 +827,10 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) return (position + crtc->scanline_offset) % vtotal; } -static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, - unsigned int flags, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode) +static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, + bool in_vblank_irq, int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, @@ -838,13 +838,12 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; bool in_vbl = true; - int ret = 0; unsigned long irqflags; if (WARN_ON(!mode->crtc_clock)) { DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " "pipe %c\n", pipe_name(pipe)); - return 0; + return false; } htotal = mode->crtc_htotal; @@ -859,8 +858,6 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, vtotal /= 2; } - ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; - /* * Lock uncore.lock, as we will do multiple timing critical raw * register reads, potentially with preemption disabled, so the @@ -944,11 +941,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, *hpos = position - (*vpos * htotal); } - /* In vblank? */ - if (in_vbl) - ret |= DRM_SCANOUTPOS_IN_VBLANK; - - return ret; + return true; } int intel_get_crtc_scanline(struct intel_crtc *crtc) @@ -964,37 +957,6 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc) return position; } -static bool i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, - int *max_error, - struct timeval *vblank_time, - bool in_vblank_irq) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc; - - if (pipe >= INTEL_INFO(dev_priv)->num_pipes) { - DRM_ERROR("Invalid crtc %u\n", pipe); - return false; - } - - /* Get drm_crtc to timestamp: */ - crtc = intel_get_crtc_for_pipe(dev_priv, pipe); - if (crtc == NULL) { - DRM_ERROR("Invalid crtc %u\n", pipe); - return false; - } - - if (!crtc->base.hwmode.crtc_clock) { - DRM_DEBUG_KMS("crtc %u is disabled\n", pipe); - return false; - } - - /* Helper routine in DRM core does all the work: */ - return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, - vblank_time, in_vblank_irq, - &crtc->base.hwmode); -} - static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv) { u32 busy_up, busy_down, max_avg, min_avg; @@ -4294,7 +4256,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; - dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; + dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; if (IS_CHERRYVIEW(dev_priv)) { |