summaryrefslogtreecommitdiffstats
path: root/include/drm
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2017-05-09 16:03:28 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-05-10 10:21:31 +0200
commit1bf6ad622b9be58484279978f85716fbb10d545b (patch)
treef7add5183253140848bff995e5084e8fd35dacb8 /include/drm
parent2a39b88bc121645e95a2b3b25a97ef4ceb4208b8 (diff)
downloadlinux-1bf6ad622b9be58484279978f85716fbb10d545b.tar.bz2
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 'include/drm')
-rw-r--r--include/drm/drmP.h8
-rw-r--r--include/drm/drm_drv.h20
-rw-r--r--include/drm/drm_irq.h15
3 files changed, 19 insertions, 24 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index a1b19bf45fb3..52085832f711 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -320,14 +320,6 @@ struct pci_controller;
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-/* Flags and return codes for get_vblank_timestamp() driver function. */
-#define DRM_CALLED_FROM_VBLIRQ 1
-
-/* get_scanout_position() return flags */
-#define DRM_SCANOUTPOS_VALID (1 << 0)
-#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
-#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
-
/**
* DRM device structure. This structure represent a complete card that
* may contain multiple heads.
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 619da98533cd..e64e33b9dd26 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -265,16 +265,8 @@ struct drm_driver {
*
* Returns:
*
- * Flags, or'ed together as follows:
- *
- * DRM_SCANOUTPOS_VALID:
- * Query successful.
- * DRM_SCANOUTPOS_INVBL:
- * Inside vblank.
- * DRM_SCANOUTPOS_ACCURATE: Returned position is accurate. A lack of
- * this flag means that returned position may be offset by a
- * constant but unknown small number of scanlines wrt. real scanout
- * position.
+ * True on success, false if a reliable scanout position counter could
+ * not be read out.
*
* FIXME:
*
@@ -282,10 +274,10 @@ struct drm_driver {
* move it to &struct drm_crtc_helper_funcs, like all the other
* helper-internal hooks.
*/
- int (*get_scanout_position) (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);
+ bool (*get_scanout_position) (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);
/**
* @get_vblank_timestamp:
diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h
index 445406efb8dc..569ca86d4e1f 100644
--- a/include/drm/drm_irq.h
+++ b/include/drm/drm_irq.h
@@ -121,6 +121,18 @@ struct drm_vblank_crtc {
* drm_calc_timestamping_constants().
*/
int linedur_ns;
+
+ /**
+ * @hwmode:
+ *
+ * Cache of the current hardware display mode. Only valid when @enabled
+ * is set. This is used by helpers like
+ * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the
+ * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode,
+ * because that one is really hard to get from interrupt context.
+ */
+ struct drm_display_mode hwmode;
+
/**
* @enabled: Tracks the enabling state of the corresponding &drm_crtc to
* avoid double-disabling and hence corrupting saved state. Needed by
@@ -156,8 +168,7 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc);
bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
unsigned int pipe, int *max_error,
struct timeval *vblank_time,
- bool in_vblank_irq,
- const struct drm_display_mode *mode);
+ bool in_vblank_irq);
void drm_calc_timestamping_constants(struct drm_crtc *crtc,
const struct drm_display_mode *mode);