drm/vblank: drop the mode argument from drm_calc_vbltimestamp_from_scanoutpos
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 9 May 2017 14:03:28 +0000 (16:03 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 10 May 2017 08:21:31 +0000 (10:21 +0200)
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
19 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.h
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_drv.h
include/drm/drmP.h
include/drm/drm_drv.h
include/drm/drm_irq.h

index 0ce8292d97c0383a5b5c052c1dbc19a151d40fd3..9de615bb0c2e517d01d23c422b29f62a58db586c 100644 (file)
@@ -1910,10 +1910,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon);
 u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
 int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
 void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
-bool amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
-                                    int *max_error,
-                                    struct timeval *vblank_time,
-                                    bool in_vblank_irq);
 long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
 
index 4e0f7d2d87f19f26ddf0900c3d5587f32cd62bce..73e982cd6136ab12fe13a4cd67f1a18d775c4c33 100644 (file)
@@ -711,6 +711,16 @@ static const struct file_operations amdgpu_driver_kms_fops = {
 #endif
 };
 
+static bool
+amdgpu_get_crtc_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)
+{
+       return amdgpu_get_crtc_scanoutpos(dev, pipe, 0, vpos, hpos,
+                                         stime, etime, mode);
+}
+
 static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP |
@@ -725,8 +735,8 @@ static struct drm_driver kms_driver = {
        .get_vblank_counter = amdgpu_get_vblank_counter_kms,
        .enable_vblank = amdgpu_enable_vblank_kms,
        .disable_vblank = amdgpu_disable_vblank_kms,
-       .get_vblank_timestamp = amdgpu_get_vblank_timestamp_kms,
-       .get_scanout_position = amdgpu_get_crtc_scanoutpos,
+       .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
+       .get_scanout_position = amdgpu_get_crtc_scanout_position,
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = amdgpu_debugfs_init,
 #endif
index babd969a63d1306aabc6e01e635956cf436a1471..40f45ba71b8686783b0daa9d93438af430315e6a 100644 (file)
@@ -934,47 +934,6 @@ void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe)
        amdgpu_irq_put(adev, &adev->crtc_irq, idx);
 }
 
-/**
- * amdgpu_get_vblank_timestamp_kms - get vblank timestamp
- *
- * @dev: drm dev pointer
- * @crtc: crtc to get the timestamp for
- * @max_error: max error
- * @vblank_time: time value
- * @in_vblank_irq: called from drm_handle_vblank()
- *
- * Gets the timestamp on the requested crtc based on the
- * scanout position.  (all asics).
- * Returns true on success, false on failure.
- */
-bool amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
-                                    int *max_error,
-                                    struct timeval *vblank_time,
-                                    bool in_vblank_irq)
-{
-       struct drm_crtc *crtc;
-       struct amdgpu_device *adev = dev->dev_private;
-
-       if (pipe >= dev->num_crtcs) {
-               DRM_ERROR("Invalid crtc %u\n", pipe);
-               return false;
-       }
-
-       /* Get associated drm_crtc: */
-       crtc = &adev->mode_info.crtcs[pipe]->base;
-       if (!crtc) {
-               /* This can occur on driver load if some component fails to
-                * initialize completely and driver is unloaded */
-               DRM_ERROR("Uninitialized crtc %d\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->hwmode);
-}
-
 const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
        DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
index db8f8dda209c7880b0ede9e79268a7c9726b3b5c..20d6522fd7b45a96ec1ac74447756537bf35a452 100644 (file)
@@ -534,6 +534,9 @@ struct amdgpu_framebuffer {
                                ((em) == ATOM_ENCODER_MODE_DP_MST))
 
 /* Driver internal use only flags of amdgpu_get_crtc_scanoutpos() */
+#define DRM_SCANOUTPOS_VALID        (1 << 0)
+#define DRM_SCANOUTPOS_IN_VBLANK    (1 << 1)
+#define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
 #define USE_REAL_VBLANKSTART           (1 << 30)
 #define GET_DISTANCE_TO_VBLANKSTART    (1 << 31)
 
index fba6a842f4cd4ac1c1a19405f00dcd0cb9015eca..89f0928b042af6d619d16864fbfb7077bf3135ca 100644 (file)
@@ -684,6 +684,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
 
        vblank->linedur_ns  = linedur_ns;
        vblank->framedur_ns = framedur_ns;
+       vblank->hwmode = *mode;
 
        DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
                  crtc->base.id, mode->crtc_htotal,
@@ -704,7 +705,6 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
  *     True when called from drm_crtc_handle_vblank().  Some drivers
  *     need to apply some workarounds for gpu-specific vblank irq quirks
  *     if flag is set.
- * @mode: mode which defines the scanout timings
  *
  * Implements calculation of exact vblank timestamps from given drm_display_mode
  * timings and current video scanout position of a CRTC. This can be called from
@@ -724,6 +724,13 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
  * returns as no operation if a doublescan or interlaced video mode is
  * active. Higher level code is expected to handle this.
  *
+ * This function can be used to implement the &drm_driver.get_vblank_timestamp
+ * directly, if the driver implements the &drm_driver.get_scanout_position hook.
+ *
+ * Note that atomic drivers must call drm_calc_timestamping_constants() before
+ * enabling a CRTC. The atomic helpers already take care of that in
+ * drm_atomic_helper_update_legacy_modeset_state().
+ *
  * Returns:
  *
  * Returns true on success, and false on failure, i.e. when no accurate
@@ -733,17 +740,23 @@ 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)
 {
        struct timeval tv_etime;
        ktime_t stime, etime;
-       unsigned int vbl_status;
+       bool vbl_status;
+       struct drm_crtc *crtc;
+       const struct drm_display_mode *mode;
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        int vpos, hpos, i;
        int delta_ns, duration_ns;
-       unsigned flags = in_vblank_irq ? DRM_CALLED_FROM_VBLIRQ : 0;
 
-       if (pipe >= dev->num_crtcs) {
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return false;
+
+       crtc = drm_crtc_from_index(dev, pipe);
+
+       if (pipe >= dev->num_crtcs || !crtc) {
                DRM_ERROR("Invalid crtc %u\n", pipe);
                return false;
        }
@@ -754,6 +767,11 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
                return false;
        }
 
+       if (drm_drv_uses_atomic_modeset(dev))
+               mode = &vblank->hwmode;
+       else
+               mode = &crtc->hwmode;
+
        /* If mode timing undefined, just return as no-op:
         * Happens during initial modesetting of a crtc.
         */
@@ -774,15 +792,16 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
                 * Get vertical and horizontal scanout position vpos, hpos,
                 * and bounding timestamps stime, etime, pre/post query.
                 */
-               vbl_status = dev->driver->get_scanout_position(dev, pipe, flags,
+               vbl_status = dev->driver->get_scanout_position(dev, pipe,
+                                                              in_vblank_irq,
                                                               &vpos, &hpos,
                                                               &stime, &etime,
                                                               mode);
 
                /* Return as no-op if scanout query unsupported or failed. */
-               if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
-                       DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n",
-                                 pipe, vbl_status);
+               if (!vbl_status) {
+                       DRM_DEBUG("crtc %u : scanoutpos query failed.\n",
+                                 pipe);
                        return false;
                }
 
@@ -821,8 +840,8 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
        etime = ktime_sub_ns(etime, delta_ns);
        *vblank_time = ktime_to_timeval(etime);
 
-       DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
-                     pipe, vbl_status, hpos, vpos,
+       DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
+                     pipe, hpos, vpos,
                      (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
                      (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
                      duration_ns/1000, i);
index ae09c29662a17fcfa6fa4a88ed7e2be107488d8f..dccb7c2560fe40c2364c61f73280f6d49510ce95 100644 (file)
@@ -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)) {
index 07e2b1335f65b31be9feb23deb9f55ea8c5f4e9f..e2b3346ead48fb49aae2b278a49cd45c960afacb 100644 (file)
@@ -527,31 +527,28 @@ static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
        return NULL;
 }
 
-static int mdp5_get_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 mdp5_get_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 msm_drm_private *priv = dev->dev_private;
        struct drm_crtc *crtc;
        struct drm_encoder *encoder;
        int line, vsw, vbp, vactive_start, vactive_end, vfp_end;
-       int ret = 0;
 
        crtc = priv->crtcs[pipe];
        if (!crtc) {
                DRM_ERROR("Invalid crtc %d\n", pipe);
-               return 0;
+               return false;
        }
 
        encoder = get_encoder_from_crtc(crtc);
        if (!encoder) {
                DRM_ERROR("no encoder found for crtc %d\n", pipe);
-               return 0;
+               return false;
        }
 
-       ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
-
        vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
        vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
 
@@ -575,10 +572,8 @@ static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
 
        if (line < vactive_start) {
                line -= vactive_start;
-               ret |= DRM_SCANOUTPOS_IN_VBLANK;
        } else if (line > vactive_end) {
                line = line - vfp_end - vactive_start;
-               ret |= DRM_SCANOUTPOS_IN_VBLANK;
        } else {
                line -= vactive_start;
        }
@@ -589,31 +584,7 @@ static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
        if (etime)
                *etime = ktime_get();
 
-       return ret;
-}
-
-static bool mdp5_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
-                                     int *max_error,
-                                     struct timeval *vblank_time,
-                                     bool in_vblank_irq)
-{
-       struct msm_drm_private *priv = dev->dev_private;
-       struct drm_crtc *crtc;
-
-       if (pipe < 0 || pipe >= priv->num_crtcs) {
-               DRM_ERROR("Invalid crtc %d\n", pipe);
-               return false;
-       }
-
-       crtc = priv->crtcs[pipe];
-       if (!crtc) {
-               DRM_ERROR("Invalid crtc %d\n", pipe);
-               return false;
-       }
-
-       return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
-                                                    vblank_time, in_vblank_irq,
-                                                    &crtc->mode);
+       return true;
 }
 
 static u32 mdp5_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
@@ -725,7 +696,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
        dev->mode_config.max_width = 0xffff;
        dev->mode_config.max_height = 0xffff;
 
-       dev->driver->get_vblank_timestamp = mdp5_get_vblank_timestamp;
+       dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos;
        dev->driver->get_scanout_position = mdp5_get_scanoutpos;
        dev->driver->get_vblank_counter = mdp5_get_vblank_counter;
        dev->max_vblank_count = 0xffffffff;
index 2d28ef57f2bfdf5467ac349e0907c971f592fc86..6718c84fb86250f2bb68a4612a5209ed5725cee4 100644 (file)
@@ -98,7 +98,7 @@ calc(int blanks, int blanke, int total, int line)
        return line;
 }
 
-static int
+static bool
 nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
                                ktime_t *stime, ktime_t *etime)
 {
@@ -111,16 +111,16 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
        };
        struct nouveau_display *disp = nouveau_display(crtc->dev);
        struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
-       int ret, retry = 20;
+       int retry = 20;
+       bool ret = false;
 
        do {
                ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args));
                if (ret != 0)
-                       return 0;
+                       return false;
 
                if (args.scan.vline) {
-                       ret |= DRM_SCANOUTPOS_ACCURATE;
-                       ret |= DRM_SCANOUTPOS_VALID;
+                       ret = true;
                        break;
                }
 
@@ -133,14 +133,12 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
        if (stime) *stime = ns_to_ktime(args.scan.time[0]);
        if (etime) *etime = ns_to_ktime(args.scan.time[1]);
 
-       if (*vpos < 0)
-               ret |= DRM_SCANOUTPOS_IN_VBLANK;
        return ret;
 }
 
-int
+bool
 nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe,
-                          unsigned int flags, int *vpos, int *hpos,
+                          bool in_vblank_irq, int *vpos, int *hpos,
                           ktime_t *stime, ktime_t *etime,
                           const struct drm_display_mode *mode)
 {
@@ -153,28 +151,6 @@ nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe,
                }
        }
 
-       return 0;
-}
-
-bool
-nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe,
-                        int *max_error, struct timeval *time, bool in_vblank_irq)
-{
-       struct drm_crtc *crtc;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (nouveau_crtc(crtc)->index == pipe) {
-                       struct drm_display_mode *mode;
-                       if (drm_drv_uses_atomic_modeset(dev))
-                               mode = &crtc->state->adjusted_mode;
-                       else
-                               mode = &crtc->hwmode;
-                       return drm_calc_vbltimestamp_from_scanoutpos(dev,
-                                       pipe, max_error, time, in_vblank_irq,
-                                       mode);
-               }
-       }
-
        return false;
 }
 
index 8ec86259c5ac14c5070c929c416b16e18a6a4acb..201aec2ea5b81c690e10c6765e0a406ec9af197c 100644 (file)
@@ -68,11 +68,9 @@ int  nouveau_display_suspend(struct drm_device *dev, bool runtime);
 void nouveau_display_resume(struct drm_device *dev, bool runtime);
 int  nouveau_display_vblank_enable(struct drm_device *, unsigned int);
 void nouveau_display_vblank_disable(struct drm_device *, unsigned int);
-int  nouveau_display_scanoutpos(struct drm_device *, unsigned int,
-                               unsigned int, int *, int *, ktime_t *,
-                               ktime_t *, const struct drm_display_mode *);
-bool  nouveau_display_vblstamp(struct drm_device *, unsigned int, int *,
-                              struct timeval *, bool);
+bool  nouveau_display_scanoutpos(struct drm_device *, unsigned int,
+                                bool, int *, int *, ktime_t *,
+                                ktime_t *, const struct drm_display_mode *);
 
 int  nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                            struct drm_pending_vblank_event *event,
index ec719df619a624c3e753af6ef72de68d21d5ad83..1f751a3f570ce5190d29556e418b3ae7e59804dc 100644 (file)
@@ -978,7 +978,7 @@ driver_stub = {
        .enable_vblank = nouveau_display_vblank_enable,
        .disable_vblank = nouveau_display_vblank_disable,
        .get_scanout_position = nouveau_display_scanoutpos,
-       .get_vblank_timestamp = nouveau_display_vblstamp,
+       .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
 
        .ioctls = nouveau_ioctls,
        .num_ioctls = ARRAY_SIZE(nouveau_ioctls),
index 88fc791ec8fb88ef1fb9187e794a285cb19a4b23..ef8a759409804bf74076986395fee5e536e674a5 100644 (file)
@@ -115,10 +115,6 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
 u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
 int radeon_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
 void radeon_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
-bool radeon_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
-                                    int *max_error,
-                                    struct timeval *vblank_time,
-                                    bool in_vblank_irq);
 void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
 int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
 void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
@@ -530,6 +526,16 @@ static const struct file_operations radeon_driver_kms_fops = {
 #endif
 };
 
+static bool
+radeon_get_crtc_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)
+{
+       return radeon_get_crtc_scanoutpos(dev, pipe, 0, vpos, hpos,
+                                         stime, etime, mode);
+}
+
 static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP |
@@ -544,8 +550,8 @@ static struct drm_driver kms_driver = {
        .get_vblank_counter = radeon_get_vblank_counter_kms,
        .enable_vblank = radeon_enable_vblank_kms,
        .disable_vblank = radeon_disable_vblank_kms,
-       .get_vblank_timestamp = radeon_get_vblank_timestamp_kms,
-       .get_scanout_position = radeon_get_crtc_scanoutpos,
+       .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
+       .get_scanout_position = radeon_get_crtc_scanout_position,
        .irq_preinstall = radeon_driver_irq_preinstall_kms,
        .irq_postinstall = radeon_driver_irq_postinstall_kms,
        .irq_uninstall = radeon_driver_irq_uninstall_kms,
index 5bccdeae0773cd372117cc5f201a28f6f6bc09cd..6a68d440bc4486b73a8c3433dd5083c42fb8d2ef 100644 (file)
@@ -858,43 +858,6 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
        spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
 }
 
-/**
- * radeon_get_vblank_timestamp_kms - get vblank timestamp
- *
- * @dev: drm dev pointer
- * @crtc: crtc to get the timestamp for
- * @max_error: max error
- * @vblank_time: time value
- * @flags: flags passed to the driver
- *
- * Gets the timestamp on the requested crtc based on the
- * scanout position.  (all asics).
- * Returns true on success, false on failure.
- */
-bool radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
-                                    int *max_error,
-                                    struct timeval *vblank_time,
-                                    bool in_vblank_irq)
-{
-       struct drm_crtc *drmcrtc;
-       struct radeon_device *rdev = dev->dev_private;
-
-       if (crtc < 0 || crtc >= dev->num_crtcs) {
-               DRM_ERROR("Invalid crtc %d\n", crtc);
-               return false;
-       }
-
-       /* Get associated drm_crtc: */
-       drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
-       if (!drmcrtc)
-               return false;
-
-       /* Helper routine in DRM core does all the work: */
-       return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
-                                                    vblank_time, in_vblank_irq,
-                                                    &drmcrtc->hwmode);
-}
-
 const struct drm_ioctl_desc radeon_ioctls_kms[] = {
        DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(RADEON_CP_START, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
index ad282648fc8b1e70adcd135b5618a56d818823ce..00f5ec5c12c7afba423876584648aa0ce7d05131 100644 (file)
@@ -691,6 +691,9 @@ struct atom_voltage_table
 };
 
 /* Driver internal use only flags of radeon_get_crtc_scanoutpos() */
+#define DRM_SCANOUTPOS_VALID        (1 << 0)
+#define DRM_SCANOUTPOS_IN_VBLANK    (1 << 1)
+#define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
 #define USE_REAL_VBLANKSTART           (1 << 30)
 #define GET_DISTANCE_TO_VBLANKSTART    (1 << 31)
 
index 6ed53d2867c4821f7065f57f75846cb2d6b40335..1b4dbe9e1c6d5816bb6f02e42aeccd6f42a23c19 100644 (file)
@@ -151,10 +151,10 @@ int vc4_crtc_debugfs_regs(struct seq_file *m, void *unused)
 }
 #endif
 
-int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
-                           unsigned int flags, int *vpos, int *hpos,
-                           ktime_t *stime, ktime_t *etime,
-                           const struct drm_display_mode *mode)
+bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
+                            bool in_vblank_irq, int *vpos, int *hpos,
+                            ktime_t *stime, ktime_t *etime,
+                            const struct drm_display_mode *mode)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id);
@@ -162,7 +162,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
        u32 val;
        int fifo_lines;
        int vblank_lines;
-       int ret = 0;
+       bool ret = false;
 
        /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
 
@@ -198,7 +198,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
        fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay;
 
        if (fifo_lines > 0)
-               ret |= DRM_SCANOUTPOS_VALID;
+               ret = true;
 
        /* HVS more than fifo_lines into frame for compositing? */
        if (*vpos > fifo_lines) {
@@ -216,7 +216,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
                 */
                *vpos -= fifo_lines + 1;
 
-               ret |= DRM_SCANOUTPOS_ACCURATE;
                return ret;
        }
 
@@ -229,10 +228,9 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
         * We can't get meaningful readings wrt. scanline position of the PV
         * and need to make things up in a approximative but consistent way.
         */
-       ret |= DRM_SCANOUTPOS_IN_VBLANK;
        vblank_lines = mode->vtotal - mode->vdisplay;
 
-       if (flags & DRM_CALLED_FROM_VBLIRQ) {
+       if (in_vblank_irq) {
                /*
                 * Assume the irq handler got called close to first
                 * line of vblank, so PV has about a full vblank
@@ -254,9 +252,10 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
                 * we are at the very beginning of vblank, as the hvs just
                 * started refilling, and the stime and etime timestamps
                 * truly correspond to start of vblank.
+                *
+                * Unfortunately there's no way to report this to upper levels
+                * and make it more useful.
                 */
-               if ((val & SCALER_DISPSTATX_FULL) != SCALER_DISPSTATX_FULL)
-                       ret |= DRM_SCANOUTPOS_ACCURATE;
        } else {
                /*
                 * No clue where we are inside vblank. Return a vpos of zero,
@@ -270,19 +269,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
        return ret;
 }
 
-bool vc4_crtc_get_vblank_timestamp(struct drm_device *dev, unsigned int crtc_id,
-                                 int *max_error, struct timeval *vblank_time,
-                                 bool in_vblank_irq)
-{
-       struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id);
-       struct drm_crtc_state *state = crtc->state;
-
-       /* Helper routine in DRM core does all the work: */
-       return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc_id, max_error,
-                                                    vblank_time, in_vblank_irq,
-                                                    &state->adjusted_mode);
-}
-
 static void vc4_crtc_destroy(struct drm_crtc *crtc)
 {
        drm_crtc_cleanup(crtc);
index 754ce76d4b980a380770b46431c6ddb91d3b06e2..863974942c662f5f3300c8637b4daa3324765ecf 100644 (file)
@@ -154,7 +154,7 @@ static struct drm_driver vc4_drm_driver = {
        .irq_uninstall = vc4_irq_uninstall,
 
        .get_scanout_position = vc4_crtc_get_scanoutpos,
-       .get_vblank_timestamp = vc4_crtc_get_vblank_timestamp,
+       .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
 
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = vc4_debugfs_init,
index d192f7e5c1ebf6f3d90ddbb438bc4ba7c15a0755..5ba281361fb7fbb1b2af87ded378721c6793e291 100644 (file)
@@ -489,13 +489,10 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
 extern struct platform_driver vc4_crtc_driver;
 bool vc4_event_pending(struct drm_crtc *crtc);
 int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
-int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
-                           unsigned int flags, int *vpos, int *hpos,
-                           ktime_t *stime, ktime_t *etime,
-                           const struct drm_display_mode *mode);
-bool vc4_crtc_get_vblank_timestamp(struct drm_device *dev, unsigned int crtc_id,
-                                 int *max_error, struct timeval *vblank_time,
-                                 bool in_vblank_irq);
+bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
+                            bool in_vblank_irq, int *vpos, int *hpos,
+                            ktime_t *stime, ktime_t *etime,
+                            const struct drm_display_mode *mode);
 
 /* vc4_debugfs.c */
 int vc4_debugfs_init(struct drm_minor *minor);
index a1b19bf45fb3e2ad42e320d5cc44dbd1c222187d..52085832f7110479405bdc228427f39534abaf02 100644 (file)
@@ -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.
index 619da98533cd5374146161dc4008451715510565..e64e33b9dd26ba96c8431b6616a895445f9f3cee 100644 (file)
@@ -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:
index 445406efb8dc463b30c994647a7878194e04174b..569ca86d4e1f0c22e98e20b02ff0bc7fe952cd35 100644 (file)
@@ -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);