Browse Source

drm/i915: add get_vblank_counter function for GM45

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>
Jesse Barnes 16 years ago
parent
commit
9880b7a527

+ 4 - 0
drivers/gpu/drm/i915/i915_dma.c

@@ -1112,6 +1112,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	dev_priv->has_gem = 1;
 	dev_priv->has_gem = 1;
 #endif
 #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);
 	i915_gem_load(dev);
 
 
 	/* Init HWS */
 	/* Init HWS */

+ 0 - 1
drivers/gpu/drm/i915/i915_drv.c

@@ -112,7 +112,6 @@ static struct drm_driver driver = {
 	.suspend = i915_suspend,
 	.suspend = i915_suspend,
 	.resume = i915_resume,
 	.resume = i915_resume,
 	.device_is_agp = i915_driver_device_is_agp,
 	.device_is_agp = i915_driver_device_is_agp,
-	.get_vblank_counter = i915_get_vblank_counter,
 	.enable_vblank = i915_enable_vblank,
 	.enable_vblank = i915_enable_vblank,
 	.disable_vblank = i915_disable_vblank,
 	.disable_vblank = i915_disable_vblank,
 	.irq_preinstall = i915_driver_irq_preinstall,
 	.irq_preinstall = i915_driver_irq_preinstall,

+ 1 - 0
drivers/gpu/drm/i915/i915_drv.h

@@ -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 int i915_enable_vblank(struct drm_device *dev, int crtc);
 extern void i915_disable_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 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,
 extern int i915_vblank_swap(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv);
 			    struct drm_file *file_priv);
 extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
 extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);

+ 13 - 0
drivers/gpu/drm/i915/i915_irq.c

@@ -174,6 +174,19 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
 	return count;
 	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)
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
 {
 	struct drm_device *dev = (struct drm_device *) arg;
 	struct drm_device *dev = (struct drm_device *) arg;

+ 6 - 0
drivers/gpu/drm/i915/i915_reg.h

@@ -1371,6 +1371,9 @@
 #define   PIPE_FRAME_LOW_SHIFT    24
 #define   PIPE_FRAME_LOW_SHIFT    24
 #define   PIPE_PIXEL_MASK         0x00ffffff
 #define   PIPE_PIXEL_MASK         0x00ffffff
 #define   PIPE_PIXEL_SHIFT        0
 #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 */
 /* Cursor A & B regs */
 #define CURACNTR		0x70080
 #define CURACNTR		0x70080
@@ -1439,6 +1442,9 @@
 #define PIPEBSTAT		0x71024
 #define PIPEBSTAT		0x71024
 #define PIPEBFRAMEHIGH		0x71040
 #define PIPEBFRAMEHIGH		0x71040
 #define PIPEBFRAMEPIXEL		0x71044
 #define PIPEBFRAMEPIXEL		0x71044
+#define PIPEB_FRMCOUNT_GM45	0x71040
+#define PIPEB_FLIPCOUNT_GM45	0x71044
+
 
 
 /* Display B control */
 /* Display B control */
 #define DSPBCNTR		0x71180
 #define DSPBCNTR		0x71180