This patch adds new functions for use by the drm core:

.get_vblank_timestamp() provides a precise timestamp
for the end of the most recent (or current) vblank
interval of a given crtc, as needed for the DRI2
implementation of the OML_sync_control extension.

It is a thin wrapper around the drm function
drm_calc_vbltimestamp_from_scanoutpos() which does
almost all the work and is shared across drivers.

.get_scanout_position() provides the current horizontal
and vertical video scanout position and "in vblank"
status of a given crtc, as needed by the drm for use by
drm_calc_vbltimestamp_from_scanoutpos().

The function is also used by the dynamic gpu reclocking
code to determine when it is safe to reclock inside vblank.

For that purpose radeon_pm_in_vbl() is modified to
accomodate a small change in the function prototype of
the radeon_get_crtc_scanoutpos() which is hooked up to
.get_scanout_position().

This code has been tested on AVIVO hardware, a RV530
(ATI Mobility Radeon X1600) in a Intel Core-2 Duo MacBookPro
and some R600 variant (FireGL V7600) in a single cpu
AMD Athlon 64 PC.

Signed-off-by: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
---
 drivers/gpu/drm/radeon/radeon_display.c |   40 ++++++++++++++++--------------
 drivers/gpu/drm/radeon/radeon_drv.c     |    8 ++++++
 drivers/gpu/drm/radeon/radeon_kms.c     |   21 ++++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h    |    7 +----
 drivers/gpu/drm/radeon/radeon_pm.c      |    6 ++--
 5 files changed, 55 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_display.c 
b/drivers/gpu/drm/radeon/radeon_display.c
index 0383631..37bfc48 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1015,7 +1015,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
 /*
  * Retrieve current video scanout position of crtc on a given gpu.
  *
- * \param rdev Device to query.
+ * \param dev Device to query.
  * \param crtc Crtc to query.
  * \param *vpos Location where vertical scanout position should be stored.
  * \param *hpos Location where horizontal scanout position should go.
@@ -1027,72 +1027,74 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc 
*crtc,
  *
  * \return Flags, or'ed together as follows:
  *
- * RADEON_SCANOUTPOS_VALID = Query successfull.
- * RADEON_SCANOUTPOS_INVBL = Inside vblank.
- * RADEON_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
+ * DRM_SCANOUTPOS_VALID = Query successfull.
+ * 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 radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int 
*vpos, int *hpos)
+int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, 
int *hpos)
 {
        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;
+
        if (ASIC_IS_DCE4(rdev)) {
                if (crtc == 0) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC0_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC0_REGISTER_OFFSET);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
                if (crtc == 1) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC1_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC1_REGISTER_OFFSET);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
                if (crtc == 2) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC2_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC2_REGISTER_OFFSET);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
                if (crtc == 3) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC3_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC3_REGISTER_OFFSET);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
                if (crtc == 4) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC4_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC4_REGISTER_OFFSET);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
                if (crtc == 5) {
                        vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
                                     EVERGREEN_CRTC5_REGISTER_OFFSET);
                        position = RREG32(EVERGREEN_CRTC_STATUS_POSITION +
                                          EVERGREEN_CRTC5_REGISTER_OFFSET);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
        } else if (ASIC_IS_AVIVO(rdev)) {
                if (crtc == 0) {
                        vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END);
                        position = RREG32(AVIVO_D1CRTC_STATUS_POSITION);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
                if (crtc == 1) {
                        vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END);
                        position = RREG32(AVIVO_D2CRTC_STATUS_POSITION);
-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
        } else {
                /* Pre-AVIVO: Different encoding of scanout pos and vblank 
interval. */
@@ -1108,7 +1110,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device 
*rdev, int crtc, int *vpos,
                        if (!(stat_crtc & 1))
                                in_vbl = false;

-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
                if (crtc == 1) {
                        vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) &
@@ -1118,7 +1120,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device 
*rdev, int crtc, int *vpos,
                        if (!(stat_crtc & 1))
                                in_vbl = false;

-                       ret |= RADEON_SCANOUTPOS_VALID;
+                       ret |= DRM_SCANOUTPOS_VALID;
                }
        }

@@ -1129,13 +1131,13 @@ int radeon_get_crtc_scanoutpos(struct radeon_device 
*rdev, int crtc, int *vpos,
        /* Valid vblank area boundaries from gpu retrieved? */
        if (vbl > 0) {
                /* Yes: Decode. */
-               ret |= RADEON_SCANOUTPOS_ACCURATE;
+               ret |= DRM_SCANOUTPOS_ACCURATE;
                vbl_start = vbl & 0x1fff;
                vbl_end = (vbl >> 16) & 0x1fff;
        }
        else {
                /* No: Fake something reasonable which gives at least ok 
results. */
-               vbl_start = 
rdev->mode_info.crtcs[crtc]->base.mode.crtc_vdisplay;
+               vbl_start = 
rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
                vbl_end = 0;
        }

@@ -1151,7 +1153,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device 
*rdev, int crtc, int *vpos,

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

@@ -1160,7 +1162,7 @@ int radeon_get_crtc_scanoutpos(struct radeon_device 
*rdev, int crtc, int *vpos,

        /* In vblank? */
        if (in_vbl)
-               ret |= RADEON_SCANOUTPOS_INVBL;
+               ret |= DRM_SCANOUTPOS_INVBL;

        return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index f29a269..a588a5b 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -65,6 +65,10 @@ int radeon_resume_kms(struct drm_device *dev);
 u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc);
 int radeon_enable_vblank_kms(struct drm_device *dev, int crtc);
 void radeon_disable_vblank_kms(struct drm_device *dev, int crtc);
+int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
+                                   int *max_error,
+                                   struct timeval *vblank_time,
+                                   unsigned flags);
 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);
@@ -73,6 +77,8 @@ int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
                         struct drm_file *file_priv);
 int radeon_gem_object_init(struct drm_gem_object *obj);
 void radeon_gem_object_free(struct drm_gem_object *obj);
+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+                                     int *vpos, int *hpos);
 extern struct drm_ioctl_desc radeon_ioctls_kms[];
 extern int radeon_max_kms_ioctl;
 int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -275,6 +281,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,
 #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 8fbbe1c..4bf423c 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -277,6 +277,27 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int 
crtc)
        radeon_irq_set(rdev);
 }

+int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
+                                   int *max_error,
+                                   struct timeval *vblank_time,
+                                   unsigned flags)
+{
+       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 -EINVAL;
+       }
+
+       /* Get associated drm_crtc: */
+       drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
+
+       /* Helper routine in DRM core does all the work: */
+       return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
+                                                    vblank_time, flags,
+                                                    drmcrtc);
+}

 /*
  * IOCTL.
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h 
b/drivers/gpu/drm/radeon/radeon_mode.h
index 61b9243..5d8d4fa 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -435,10 +435,6 @@ struct radeon_framebuffer {
        struct drm_gem_object *obj;
 };

-/* radeon_get_crtc_scanoutpos() return flags */
-#define RADEON_SCANOUTPOS_VALID        (1 << 0)
-#define RADEON_SCANOUTPOS_INVBL        (1 << 1)
-#define RADEON_SCANOUTPOS_ACCURATE     (1 << 2)

 extern enum radeon_tv_std
 radeon_combios_get_tv_info(struct radeon_device *rdev);
@@ -553,7 +549,8 @@ extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
 extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                                   int x, int y);

-extern int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, 
int *vpos, int *hpos);
+extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
+                                     int *vpos, int *hpos);

 extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev);
 extern struct edid *
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c 
b/drivers/gpu/drm/radeon/radeon_pm.c
index 8c9b2ef..5eda5e4 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -720,9 +720,9 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
         */
        for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
                if (rdev->pm.active_crtcs & (1 << crtc)) {
-                       vbl_status = radeon_get_crtc_scanoutpos(rdev, crtc, 
&vpos, &hpos);
-                       if ((vbl_status & RADEON_SCANOUTPOS_VALID) &&
-                           !(vbl_status & RADEON_SCANOUTPOS_INVBL))
+                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, 
crtc, &vpos, &hpos);
+                       if ((vbl_status & DRM_SCANOUTPOS_VALID) &&
+                           !(vbl_status & DRM_SCANOUTPOS_INVBL))
                                in_vbl = false;
                }
        }
-- 
1.7.1

Reply via email to