From: Thierry Reding <tred...@nvidia.com>

None of the drivers use this in legacy mode, so it can be converted to
use struct drm_crtc * directly. While at it, also make the sole user of
the callback, drm_calc_vbltimestamp_from_scanoutpos(), pass through the
CRTC directly.

Cc: Daniel Vetter <daniel.vetter at intel.com>
Cc: Jani Nikula <jani.nikula at linux.intel.com>
Cc: Ben Skeggs <bskeggs at redhat.com>
Cc: Alex Deucher <alexander.deucher at amd.com>
Cc: Christian König <christian.koenig at amd.com>
Signed-off-by: Thierry Reding <treding at nvidia.com>
---
Note: This is compile-tested only. It is a straightforward conversion so
I wouldn't expect any fallout, but it'd certainly be best if this can be
tested on all three drivers.

 drivers/gpu/drm/drm_irq.c                 | 34 +++++++++-------------
 drivers/gpu/drm/i915/i915_irq.c           | 15 +++++-----
 drivers/gpu/drm/i915/intel_display.c      |  1 +
 drivers/gpu/drm/i915/intel_drv.h          |  3 ++
 drivers/gpu/drm/nouveau/dispnv04/crtc.c   |  1 +
 drivers/gpu/drm/nouveau/nouveau_display.c | 25 ++++------------
 drivers/gpu/drm/nouveau/nouveau_display.h |  4 +--
 drivers/gpu/drm/nouveau/nouveau_drm.c     |  1 -
 drivers/gpu/drm/nouveau/nv50_display.c    |  1 +
 drivers/gpu/drm/radeon/radeon_display.c   | 39 ++++++++++++-------------
 drivers/gpu/drm/radeon/radeon_drv.c       |  1 -
 drivers/gpu/drm/radeon/radeon_kms.c       |  2 +-
 drivers/gpu/drm/radeon/radeon_mode.h      |  2 +-
 drivers/gpu/drm/radeon/radeon_pm.c        |  4 ++-
 include/drm/drmP.h                        | 47 -------------------------------
 include/drm/drm_crtc.h                    | 45 +++++++++++++++++++++++++++++
 16 files changed, 104 insertions(+), 121 deletions(-)

diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 37b536c57cd2..18f1ccad7ee0 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -161,14 +161,14 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
  * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
  *
  */
-int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
-                                         unsigned int pipe,
+int drm_calc_vbltimestamp_from_scanoutpos(struct drm_crtc *crtc,
                                          int *max_error,
                                          struct timeval *vblank_time,
                                          unsigned flags,
                                          const struct drm_crtc *refcrtc,
                                          const struct drm_display_mode *mode)
 {
+       const struct drm_crtc_funcs *funcs = crtc->funcs;
        struct timeval tv_etime;
        ktime_t stime, etime;
        int vbl_status;
@@ -176,16 +176,9 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct 
drm_device *dev,
        int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
        bool invbl;

-       if (pipe >= dev->num_crtcs) {
-               DRM_ERROR("Invalid crtc %u\n", pipe);
-               return -EINVAL;
-       }
-
        /* Scanout position query not supported? Should not happen. */
-       if (!dev->driver->get_scanout_position) {
-               DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
-               return -EIO;
-       }
+       if (WARN_ON(funcs->get_scanout_position == NULL))
+               return -ENOSYS;

        /* Durations of frames, lines, pixels in nanoseconds. */
        framedur_ns = refcrtc->framedur_ns;
@@ -196,7 +189,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device 
*dev,
         * Happens during initial modesetting of a crtc.
         */
        if (framedur_ns == 0) {
-               DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe);
+               DRM_DEBUG("crtc %x: Noop due to uninitialized mode.\n",
+                         crtc->base.id);
                return -EAGAIN;
        }

@@ -212,13 +206,13 @@ int 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, &vpos,
-                                                              &hpos, &stime, 
&etime);
+               vbl_status = funcs->get_scanout_position(crtc, flags, &vpos,
+                                                        &hpos, &stime, &etime);

                /* Return as no-op if scanout query unsupported or failed. */
                if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
-                       DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n",
-                                 pipe, vbl_status);
+                       DRM_DEBUG("crtc %x: scanoutpos query failed [%d].\n",
+                                 crtc->base.id, vbl_status);
                        return -EIO;
                }

@@ -232,8 +226,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device 
*dev,

        /* Noisy system timing? */
        if (i == DRM_TIMESTAMP_MAXRETRIES) {
-               DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
-                         pipe, duration_ns/1000, *max_error/1000, i);
+               DRM_DEBUG("crtc %x: Noisy timestamp %d us > %d us [%d reps].\n",
+                         crtc->base.id, duration_ns/1000, *max_error/1000, i);
        }

        /* Return upper bound of timestamp precision error. */
@@ -266,8 +260,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device 
*dev,
                etime = ktime_sub_ns(etime, delta_ns);
        *vblank_time = ktime_to_timeval(etime);

-       DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d 
rep]\n",
-                 pipe, (int)vbl_status, hpos, vpos,
+       DRM_DEBUG("crtc %x: v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d 
rep]\n",
+                 crtc->base.id, (int)vbl_status, 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);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 996c2931c499..bc6dc51abe95 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -662,14 +662,15 @@ 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, int pipe,
-                                   unsigned int flags, int *vpos, int *hpos,
-                                   ktime_t *stime, ktime_t *etime)
+int i915_get_crtc_scanoutpos(struct drm_crtc *crtc, unsigned int flags,
+                            int *vpos, int *hpos, ktime_t *stime,
+                            ktime_t *etime)
 {
+       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
+       enum pipe pipe = intel_crtc->pipe;
        int position;
        int vbl_start, vbl_end, hsync_start, htotal, vtotal;
        bool in_vbl = true;
@@ -824,7 +825,7 @@ static int i915_get_vblank_timestamp(struct drm_device 
*dev, int pipe,
        }

        /* Helper routine in DRM core does all the work: */
-       return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
+       return drm_calc_vbltimestamp_from_scanoutpos(crtc, max_error,
                                                     vblank_time, flags,
                                                     crtc,
                                                     
&to_intel_crtc(crtc)->config.adjusted_mode);
@@ -4360,10 +4361,8 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        if (!IS_GEN2(dev_priv))
                dev->vblank_disable_immediate = true;

-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
                dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
-               dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
-       }

        if (IS_CHERRYVIEW(dev_priv)) {
                dev->driver->irq_handler = cherryview_irq_handler;
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 518815df51bd..e4e1119e6031 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11660,6 +11660,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
        .set_config = intel_crtc_set_config,
        .destroy = intel_crtc_destroy,
        .page_flip = intel_crtc_page_flip,
+       .get_scanout_position = i915_get_crtc_scanoutpos,
 };

 static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 25fdbb16d4e0..4217faeb75e0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -805,6 +805,9 @@ static inline bool intel_irqs_enabled(struct 
drm_i915_private *dev_priv)
        return dev_priv->pm.irqs_enabled;
 }

+int i915_get_crtc_scanoutpos(struct drm_crtc *crtc, unsigned int flags,
+                            int *vpos, int *hpos, ktime_t *stime,
+                            ktime_t *etime);
 int intel_get_crtc_scanline(struct intel_crtc *crtc);
 void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv);

diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c 
b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index 38402ade6835..9071ff9580d1 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -1089,6 +1089,7 @@ static const struct drm_crtc_funcs nv04_crtc_funcs = {
        .set_config = nouveau_crtc_set_config,
        .page_flip = nouveau_crtc_page_flip,
        .destroy = nv_crtc_destroy,
+       .get_scanout_position = nouveau_display_scanoutpos,
 };

 static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index 5d93902a91ab..da040508fdb2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -92,8 +92,9 @@ calc(int blanks, int blanke, int total, int line)
 }

 int
-nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
-                               ktime_t *stime, ktime_t *etime)
+nouveau_display_scanoutpos(struct drm_crtc *crtc, unsigned int flags,
+                          int *vpos, int *hpos, ktime_t *stime,
+                          ktime_t *etime)
 {
        struct {
                struct nv04_disp_mthd_v0 base;
@@ -131,22 +132,6 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int 
*vpos, int *hpos,
 }

 int
-nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int 
flags,
-                          int *vpos, int *hpos, ktime_t *stime, ktime_t *etime)
-{
-       struct drm_crtc *crtc;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (nouveau_crtc(crtc)->index == head) {
-                       return nouveau_display_scanoutpos_head(crtc, vpos, hpos,
-                                                              stime, etime);
-               }
-       }
-
-       return 0;
-}
-
-int
 nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error,
                         struct timeval *time, unsigned flags)
 {
@@ -154,8 +139,8 @@ nouveau_display_vblstamp(struct drm_device *dev, int head, 
int *max_error,

        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                if (nouveau_crtc(crtc)->index == head) {
-                       return drm_calc_vbltimestamp_from_scanoutpos(dev,
-                                       head, max_error, time, flags, crtc,
+                       return drm_calc_vbltimestamp_from_scanoutpos(crtc,
+                                       max_error, time, flags, crtc,
                                        &crtc->hwmode);
                }
        }
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h 
b/drivers/gpu/drm/nouveau/nouveau_display.h
index be3d5947c6be..e427034f0265 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -67,8 +67,8 @@ 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 *, int);
 void nouveau_display_vblank_disable(struct drm_device *, int);
-int  nouveau_display_scanoutpos(struct drm_device *, int, unsigned int,
-                               int *, int *, ktime_t *, ktime_t *);
+int  nouveau_display_scanoutpos(struct drm_crtc *, unsigned int, int *, int *,
+                               ktime_t *, ktime_t *);
 int  nouveau_display_vblstamp(struct drm_device *, int, int *,
                              struct timeval *, unsigned);

diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c 
b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 22d49438b136..b69c47a63bd9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -958,7 +958,6 @@ driver_stub = {
        .get_vblank_counter = drm_vblank_count,
        .enable_vblank = nouveau_display_vblank_enable,
        .disable_vblank = nouveau_display_vblank_disable,
-       .get_scanout_position = nouveau_display_scanoutpos,
        .get_vblank_timestamp = nouveau_display_vblstamp,

        .ioctls = nouveau_ioctls,
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c 
b/drivers/gpu/drm/nouveau/nv50_display.c
index 490b90866baf..18acbeea16bb 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1386,6 +1386,7 @@ static const struct drm_crtc_funcs nv50_crtc_func = {
        .set_config = nouveau_crtc_set_config,
        .destroy = nv50_crtc_destroy,
        .page_flip = nouveau_crtc_page_flip,
+       .get_scanout_position = nouveau_display_scanoutpos,
 };

 static int
diff --git a/drivers/gpu/drm/radeon/radeon_display.c 
b/drivers/gpu/drm/radeon/radeon_display.c
index 102116902a07..2d0f9be23112 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -322,9 +322,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, 
int crtc_id)
         * to complete in this vblank?
         */
        if (update_pending &&
-           (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, 
crtc_id, 0,
+           (DRM_SCANOUTPOS_VALID & 
radeon_crtc_get_scanoutpos(&radeon_crtc->base, 0,
                                                               &vpos, &hpos, 
NULL, NULL)) &&
-           ((vpos >= (99 * 
rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
+           ((vpos >= (99 * radeon_crtc->base.hwmode.crtc_vdisplay)/100) ||
             (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
                /* crtc didn't flip in this target vblank interval,
                 * but flip is pending in crtc. Based on the current
@@ -641,6 +641,7 @@ static const struct drm_crtc_funcs radeon_crtc_funcs = {
        .set_config = radeon_crtc_set_config,
        .destroy = radeon_crtc_destroy,
        .page_flip = radeon_crtc_page_flip,
+       .get_scanout_position = radeon_crtc_get_scanoutpos,
 };

 static void radeon_crtc_init(struct drm_device *dev, int index)
@@ -1758,7 +1759,6 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
  * Retrieve current video scanout position of crtc on a given gpu, and
  * an optional accurate timestamp of when query happened.
  *
- * \param dev Device to query.
  * \param crtc Crtc to query.
  * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
  * \param *vpos Location where vertical scanout position should be stored.
@@ -1782,14 +1782,15 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc 
*crtc,
  * unknown small number of scanlines wrt. real scanout position.
  *
  */
-int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int 
flags,
+int radeon_crtc_get_scanoutpos(struct drm_crtc *crtc, unsigned int flags,
                               int *vpos, int *hpos, ktime_t *stime, ktime_t 
*etime)
 {
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        u32 stat_crtc = 0, vbl = 0, position = 0;
        int vbl_start, vbl_end, vtotal, ret = 0;
        bool in_vbl = true;

-       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_device *rdev = crtc->dev->dev_private;

        /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */

@@ -1798,42 +1799,42 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, 
int crtc, unsigned int fl
                *stime = ktime_get();

        if (ASIC_IS_DCE4(rdev)) {
-               if (crtc == 0) {
+               if (radeon_crtc->crtc_id == 0) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC0_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC0_REGISTER_OFFSET);
                        ret |= DRM_SCANOUTPOS_VALID;
                }
-               if (crtc == 1) {
+               if (radeon_crtc->crtc_id == 1) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC1_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC1_REGISTER_OFFSET);
                        ret |= DRM_SCANOUTPOS_VALID;
                }
-               if (crtc == 2) {
+               if (radeon_crtc->crtc_id == 2) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC2_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC2_REGISTER_OFFSET);
                        ret |= DRM_SCANOUTPOS_VALID;
                }
-               if (crtc == 3) {
+               if (radeon_crtc->crtc_id == 3) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC3_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC3_REGISTER_OFFSET);
                        ret |= DRM_SCANOUTPOS_VALID;
                }
-               if (crtc == 4) {
+               if (radeon_crtc->crtc_id == 4) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC4_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC4_REGISTER_OFFSET);
                        ret |= DRM_SCANOUTPOS_VALID;
                }
-               if (crtc == 5) {
+               if (radeon_crtc->crtc_id == 5) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC5_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
@@ -1841,19 +1842,19 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, 
int crtc, unsigned int fl
                        ret |= DRM_SCANOUTPOS_VALID;
                }
        } else if (ASIC_IS_AVIVO(rdev)) {
-               if (crtc == 0) {
+               if (radeon_crtc->crtc_id == 0) {
                        vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END);
                        position = RREG32(AVIVO_D1CRTC_STATUS_POSITION);
                        ret |= DRM_SCANOUTPOS_VALID;
                }
-               if (crtc == 1) {
+               if (radeon_crtc->crtc_id == 1) {
                        vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END);
                        position = RREG32(AVIVO_D2CRTC_STATUS_POSITION);
                        ret |= DRM_SCANOUTPOS_VALID;
                }
        } else {
                /* Pre-AVIVO: Different encoding of scanout pos and vblank 
interval. */
-               if (crtc == 0) {
+               if (radeon_crtc->crtc_id == 0) {
                        /* Assume vbl_end == 0, get vbl_start from
                         * upper 16 bits.
                         */
@@ -1867,7 +1868,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, 
int crtc, unsigned int fl

                        ret |= DRM_SCANOUTPOS_VALID;
                }
-               if (crtc == 1) {
+               if (radeon_crtc->crtc_id == 1) {
                        vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) &
                                RADEON_CRTC_V_DISP) >> RADEON_CRTC_V_DISP_SHIFT;
                        position = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 
16) & RADEON_CRTC_V_TOTAL;
@@ -1898,7 +1899,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, 
int crtc, unsigned int fl
        }
        else {
                /* No: Fake something reasonable which gives at least ok 
results. */
-               vbl_start = 
rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
+               vbl_start = crtc->hwmode.crtc_vdisplay;
                vbl_end = 0;
        }

@@ -1914,7 +1915,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, 
int crtc, unsigned int fl

        /* Inside "upper part" of vblank area? Apply corrective offset if so: */
        if (in_vbl && (*vpos >= vbl_start)) {
-               vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+               vtotal = crtc->hwmode.crtc_vtotal;
                *vpos = *vpos - vtotal;
        }

@@ -1936,8 +1937,8 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, 
int crtc, unsigned int fl
         * We only do this if DRM_CALLED_FROM_VBLIRQ.
         */
        if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
-               vbl_start = 
rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
-               vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
+               vbl_start = crtc->hwmode.crtc_vdisplay;
+               vtotal = crtc->hwmode.crtc_vtotal;

                if (vbl_start - *vpos < vtotal / 100) {
                        *vpos -= vtotal;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index 4f50fb0e3d93..d1b0250dde48 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -567,7 +567,6 @@ static struct drm_driver kms_driver = {
        .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,
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = radeon_debugfs_init,
        .debugfs_cleanup = radeon_debugfs_cleanup,
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c 
b/drivers/gpu/drm/radeon/radeon_kms.c
index 3cf9c1fa6475..652f65b1080f 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -804,7 +804,7 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, 
int crtc,
                return -EINVAL;

        /* Helper routine in DRM core does all the work: */
-       return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
+       return drm_calc_vbltimestamp_from_scanoutpos(drmcrtc, max_error,
                                                     vblank_time, flags,
                                                     drmcrtc, &drmcrtc->hwmode);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h 
b/drivers/gpu/drm/radeon/radeon_mode.h
index 390db897f322..3c9fa1353261 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -820,7 +820,7 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                                   int x, int y);
 extern void radeon_cursor_reset(struct drm_crtc *crtc);

-extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+extern int radeon_crtc_get_scanoutpos(struct drm_crtc *crtc,
                                      unsigned int flags,
                                      int *vpos, int *hpos, ktime_t *stime,
                                      ktime_t *etime);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c 
b/drivers/gpu/drm/radeon/radeon_pm.c
index 32522cc940a1..aa9843b09ac8 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -1553,8 +1553,10 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
         * otherwise return in_vbl == false.
         */
        for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
+               struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
+
                if (rdev->pm.active_crtcs & (1 << crtc)) {
-                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, 
crtc, 0, &vpos, &hpos, NULL, NULL);
+                       vbl_status = 
radeon_crtc_get_scanoutpos(&radeon_crtc->base, 0, &vpos, &hpos, NULL, NULL);
                        if ((vbl_status & DRM_SCANOUTPOS_VALID) &&
                            !(vbl_status & DRM_SCANOUTPOS_IN_VBLANK))
                                in_vbl = false;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 4809b6f8be8b..90230ef1b73f 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -401,11 +401,6 @@ struct drm_master {
 #define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
 #define DRM_VBLANKTIME_IN_VBLANK         (1 << 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)
-
 /**
  * struct drm_driver - DRM driver structure
  * @load:
@@ -546,41 +541,6 @@ struct drm_driver {
        int (*device_is_agp) (struct drm_device *dev);

        /**
-        * Called by vblank timestamping code.
-        *
-        * Return the current display scanout position from a crtc, and an
-        * optional accurate ktime_get timestamp of when position was measured.
-        *
-        * \param dev  DRM device.
-        * \param crtc Id of the crtc to query.
-        * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
-        * \param *vpos Target location for current vertical scanout position.
-        * \param *hpos Target location for current horizontal scanout position.
-        * \param *stime Target location for timestamp taken immediately before
-        *               scanout position query. Can be NULL to skip timestamp.
-        * \param *etime Target location for timestamp taken immediately after
-        *               scanout position query. Can be NULL to skip timestamp.
-        *
-        * Returns vpos as a positive number while in active scanout area.
-        * Returns vpos as a negative number inside vblank, counting the number
-        * of scanlines to go until end of vblank, e.g., -1 means "one scanline
-        * until start of active scanout / end of vblank."
-        *
-        * \return 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.
-        *
-        */
-       int (*get_scanout_position) (struct drm_device *dev, int crtc,
-                                    unsigned int flags,
-                                    int *vpos, int *hpos, ktime_t *stime,
-                                    ktime_t *etime);
-
-       /**
         * Called by \c drm_get_last_vbltimestamp. Should return a precise
         * timestamp when the most recent VBLANK interval ended or will end.
         *
@@ -1081,13 +1041,6 @@ extern void drm_vblank_off(struct drm_device *dev, 
unsigned int pipe);
 extern void drm_vblank_on(struct drm_device *dev, unsigned int pipe);
 extern void drm_vblank_cleanup(struct drm_device *dev);

-extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
-                                                unsigned int pipe, int 
*max_error,
-                                                struct timeval *vblank_time,
-                                                unsigned flags,
-                                                const struct drm_crtc *refcrtc,
-                                                const struct drm_display_mode 
*mode);
-
 /**
  * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
  * @crtc: which CRTC's vblank waitqueue to retrieve
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index c1b639f55401..e9c6278921cd 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -276,6 +276,11 @@ struct drm_crtc_state {
        struct drm_atomic_state *state;
 };

+/* get_scanout_position() return flags */
+#define DRM_SCANOUTPOS_VALID        (1 << 0)
+#define DRM_SCANOUTPOS_IN_VBLANK    (1 << 1)
+#define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
+
 /**
  * struct drm_crtc_funcs - control CRTCs for a given device
  * @save: save CRTC state
@@ -292,6 +297,7 @@ struct drm_crtc_state {
  * @atomic_duplicate_state: duplicate the atomic state for this CRTC
  * @atomic_destroy_state: destroy an atomic state for this CRTC
  * @atomic_set_property: set a property on an atomic state for this CRTC
+ * @get_scanout_position: return the current scanout position
  *
  * The drm_crtc_funcs structure is the central CRTC management structure
  * in the DRM.  Each CRTC controls one or more connectors (note that the name
@@ -351,6 +357,38 @@ struct drm_crtc_funcs {
                                   struct drm_crtc_state *state,
                                   struct drm_property *property,
                                   uint64_t val);
+
+       /**
+        * Called by vblank timestamping code.
+        *
+        * Return the current display scanout position from a crtc, and an
+        * optional accurate ktime_get timestamp of when position was measured.
+        *
+        * \param crtc CRTC to query.
+        * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
+        * \param *vpos Target location for current vertical scanout position.
+        * \param *hpos Target location for current horizontal scanout position.
+        * \param *stime Target location for timestamp taken immediately before
+        *               scanout position query. Can be NULL to skip timestamp.
+        * \param *etime Target location for timestamp taken immediately after
+        *               scanout position query. Can be NULL to skip timestamp.
+        *
+        * Returns vpos as a positive number while in active scanout area.
+        * Returns vpos as a negative number inside vblank, counting the number
+        * of scanlines to go until end of vblank, e.g., -1 means "one scanline
+        * until start of active scanout / end of vblank."
+        *
+        * \return 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.
+        */
+       int (*get_scanout_position)(struct drm_crtc *crtc, unsigned int flags,
+                                   int *vpos, int *hpos, ktime_t *stime,
+                                   ktime_t *etime);
 };

 /**
@@ -1159,6 +1197,13 @@ extern void drm_crtc_wait_one_vblank(struct drm_crtc 
*crtc);
 extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
 extern void drm_crtc_vblank_on(struct drm_crtc *crtc);

+extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_crtc *crtc,
+                                                int *max_error,
+                                                struct timeval *vblank_time,
+                                                unsigned flags,
+                                                const struct drm_crtc *refcrtc,
+                                                const struct drm_display_mode 
*mode);
+
 extern void drm_calc_timestamping_constants(struct drm_crtc *crtc,
                                            const struct drm_display_mode 
*mode);

-- 
2.1.3

Reply via email to