drm/i915: add get_vblank_counter function for GM45
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 6 Feb 2009 18:22:41 +0000 (10:22 -0800)
committerDave Airlie <airlied@linux.ie>
Sun, 8 Feb 2009 11:43:04 +0000 (21:43 +1000)
As discussed in the long thread about vblank related timeouts, it turns out
GM45 has different frame count registers than previous chips.  This patch
adds support for them, which prevents us from waiting on really stale
sequence values in drm_wait_vblank (which rather than returning immediately
ends up timing out or getting interrupted).

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Dave Airlie <airlied@linux.ie>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h

index 0ded483d9ac7042f57dd2cecd3441ec349df357e..81f1cff56fd5e2ff02313849a2d9f4d412d22237 100644 (file)
@@ -1112,6 +1112,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        dev_priv->has_gem = 1;
 #endif
 
+       dev->driver->get_vblank_counter = i915_get_vblank_counter;
+       if (IS_GM45(dev))
+               dev->driver->get_vblank_counter = gm45_get_vblank_counter;
+
        i915_gem_load(dev);
 
        /* Init HWS */
index f8b3df0926c015a24bda63d9c7ed1756801c2797..aac12ee31a46e86540e7e2cba43d8cef273e27c2 100644 (file)
@@ -112,7 +112,6 @@ static struct drm_driver driver = {
        .suspend = i915_suspend,
        .resume = i915_resume,
        .device_is_agp = i915_driver_device_is_agp,
-       .get_vblank_counter = i915_get_vblank_counter,
        .enable_vblank = i915_enable_vblank,
        .disable_vblank = i915_disable_vblank,
        .irq_preinstall = i915_driver_irq_preinstall,
index a70bf77290fc8a8f4078e22cb2da2187421881a9..7325363164f84cf26a2f39bc3312753d1c31f28b 100644 (file)
@@ -535,6 +535,7 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
 extern int i915_enable_vblank(struct drm_device *dev, int crtc);
 extern void i915_disable_vblank(struct drm_device *dev, int crtc);
 extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
+extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
                            struct drm_file *file_priv);
 extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
index 6290219de6c8e832aa4209d761f7d2be0317211b..548ff2c66431ee93a205b15d84362084da7486ce 100644 (file)
@@ -174,6 +174,19 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
        return count;
 }
 
+u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
+
+       if (!i915_pipe_enabled(dev, pipe)) {
+               DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+               return 0;
+       }
+
+       return I915_READ(reg);
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
index 928e004625706bdb9fd7b7fa78960face183b245..9d6539a868b30fdf89154a0d046af1170db65836 100644 (file)
 #define   PIPE_FRAME_LOW_SHIFT    24
 #define   PIPE_PIXEL_MASK         0x00ffffff
 #define   PIPE_PIXEL_SHIFT        0
+/* GM45+ just has to be different */
+#define PIPEA_FRMCOUNT_GM45    0x70040
+#define PIPEA_FLIPCOUNT_GM45   0x70044
 
 /* Cursor A & B regs */
 #define CURACNTR               0x70080
 #define PIPEBSTAT              0x71024
 #define PIPEBFRAMEHIGH         0x71040
 #define PIPEBFRAMEPIXEL                0x71044
+#define PIPEB_FRMCOUNT_GM45    0x71040
+#define PIPEB_FLIPCOUNT_GM45   0x71044
+
 
 /* Display B control */
 #define DSPBCNTR               0x71180