diff -ru drivers/char/drm.org/radeon_drm.h drivers/char/drm/radeon_drm.h --- drivers/char/drm.org/radeon_drm.h 2008-01-24 23:58:37.000000000 +0100 +++ drivers/char/drm/radeon_drm.h 2008-07-20 17:51:08.000000000 +0200 @@ -442,6 +442,8 @@ * KW: actually it's illegal to change any of this (backwards compatibility). */ +#define SYNC_FIELDS + /* Radeon specific ioctls * The device specific ioctl range is 0x40 to 0x79. */ @@ -473,6 +475,9 @@ #define DRM_RADEON_SETPARAM 0x19 #define DRM_RADEON_SURF_ALLOC 0x1a #define DRM_RADEON_SURF_FREE 0x1b +#ifdef SYNC_FIELDS +#define DRM_RADEON_VSYNC 0x1c +#endif #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) @@ -501,6 +506,9 @@ #define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) #define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) +#ifdef SYNC_FIELDS +#define DRM_IOCTL_RADEON_VSYNC DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_VSYNC, drm_radeon_vsync_t) +#endif typedef struct drm_radeon_init { enum { @@ -722,6 +730,19 @@ unsigned int address; } drm_radeon_surface_free_t; +#ifdef SYNC_FIELDS +typedef struct drm_radeon_vsync { + struct timeval vbl_now; /* time when this ioctl() has been called */ + struct timeval vbl_since; /* time since last vertical blank */ + unsigned vbl_received; /* continuously counting blanking intervals */ + unsigned vbl_trim; /* graphics card frame rate adjust */ +} drm_radeon_vsync_t; + +#define VBL_IGNORE 0x80000000 +#define VBL_SLOWER 0x40000000 + +#endif + #define DRM_RADEON_VBLANK_CRTC1 1 #define DRM_RADEON_VBLANK_CRTC2 2 diff -ru drivers/char/drm.org/radeon_drv.h drivers/char/drm/radeon_drv.h --- drivers/char/drm.org/radeon_drv.h 2008-01-24 23:58:37.000000000 +0100 +++ drivers/char/drm/radeon_drv.h 2008-07-20 16:07:50.000000000 +0200 @@ -294,6 +294,13 @@ /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ unsigned long fb_aper_offset; + +#ifdef SYNC_FIELDS + /* sync fields circuitry */ + struct timeval vbl_last; /* remember last vblank */ + u32 trim; +#endif + } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { @@ -419,6 +426,9 @@ #define RADEON_CLOCK_CNTL_INDEX 0x0008 #define RADEON_CONFIG_APER_SIZE 0x0108 #define RADEON_CONFIG_MEMSIZE 0x00f8 +#ifdef SYNC_FIELDS +#define RADEON_CRTC_H_TOTAL_DISP 0x0200 +#endif #define RADEON_CRTC_OFFSET 0x0224 #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) diff -ru drivers/char/drm.org/radeon_irq.c drivers/char/drm/radeon_irq.c --- drivers/char/drm.org/radeon_irq.c 2008-01-24 23:58:37.000000000 +0100 +++ drivers/char/drm/radeon_irq.c 2008-07-20 20:08:06.000000000 +0200 @@ -102,6 +102,25 @@ (vblank_crtc & DRM_RADEON_VBLANK_CRTC2))) atomic_inc(&dev->vbl_received); +#ifdef SYNC_FIELDS + do_gettimeofday(&dev_priv->vbl_last); + + /* + * if requested we tamper with length of few + * horizontal lines here. + * + * don't try this at home:-) + */ + if (dev_priv->trim) { + int val = RADEON_READ(RADEON_CRTC_H_TOTAL_DISP); + int ooc = dev_priv->trim & 0xff; + + udelay(dev_priv->trim >> 16 & 0xff); + RADEON_WRITE(RADEON_CRTC_H_TOTAL_DISP, val + (dev_priv->trim & VBL_SLOWER ? ooc : -ooc)); + udelay(dev_priv->trim >> 8 & 0xff); + RADEON_WRITE(RADEON_CRTC_H_TOTAL_DISP, val); + } +#endif DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); } diff -ru drivers/char/drm.org/radeon_state.c drivers/char/drm/radeon_state.c --- drivers/char/drm.org/radeon_state.c 2008-01-24 23:58:37.000000000 +0100 +++ drivers/char/drm/radeon_state.c 2008-07-20 21:20:24.000000000 +0200 @@ -2100,6 +2100,32 @@ return 0; } +#ifdef SYNC_FIELDS +static int radeon_vsync(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + drm_radeon_vsync_t *vsyncp = (drm_radeon_vsync_t *)data; + + if (!(vsyncp->vbl_trim & VBL_IGNORE)) { + if (dev_priv->trim != vsyncp->vbl_trim) { +// printk(KERN_DEBUG "[drm] changed radeon drift trim from %x -> %x\n", dev_priv->trim, vsyncp->vbl_trim); + dev_priv->trim = vsyncp->vbl_trim; + } + } + do_gettimeofday(&vsyncp->vbl_now); + if (vsyncp->vbl_now.tv_usec < dev_priv->vbl_last.tv_usec) { + vsyncp->vbl_since.tv_sec = vsyncp->vbl_now.tv_sec - dev_priv->vbl_last.tv_sec - 1; + vsyncp->vbl_since.tv_usec = vsyncp->vbl_now.tv_usec - dev_priv->vbl_last.tv_usec + 1000000; + } else { + vsyncp->vbl_since.tv_sec = vsyncp->vbl_now.tv_sec - dev_priv->vbl_last.tv_sec; + vsyncp->vbl_since.tv_usec = vsyncp->vbl_now.tv_usec - dev_priv->vbl_last.tv_usec; + } + vsyncp->vbl_received = atomic_read(&dev->vbl_received); + vsyncp->vbl_trim = dev_priv->trim; + return 0; +} +#endif + static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -3184,7 +3210,10 @@ DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH) + DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH), +#ifdef SYNC_FIELDS + DRM_IOCTL_DEF(DRM_RADEON_VSYNC, radeon_vsync, DRM_AUTH), +#endif }; int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);