nouveau: Add read() method to Engine.timer.
authorPekka Paalanen <pq@iki.fi>
Fri, 6 Jul 2007 16:34:15 +0000 (19:34 +0300)
committerPekka Paalanen <pq@iki.fi>
Wed, 18 Jul 2007 11:12:26 +0000 (14:12 +0300)
This is not called from anywhere, yet.

shared-core/nouveau_drv.h
shared-core/nouveau_state.c
shared-core/nv04_timer.c

index f68304c..9e11f9b 100644 (file)
@@ -157,6 +157,7 @@ struct nouveau_engine_func {
 
        struct {
                int     (*init)(struct drm_device *dev);
+               uint64_t (*read)(struct drm_device *dev);
                void    (*takedown)(struct drm_device *dev);
        } timer;
 
@@ -469,6 +470,7 @@ extern void nv50_mc_takedown(struct drm_device *dev);
 
 /* nv04_timer.c */
 extern int  nv04_timer_init(struct drm_device *dev);
+extern uint64_t nv04_timer_read(struct drm_device *dev);
 extern void nv04_timer_takedown(struct drm_device *dev);
 
 extern long nouveau_compat_ioctl(struct file *filp, unsigned int cmd,
index 4e3b39d..5b67aea 100644 (file)
@@ -88,6 +88,8 @@ static int nouveau_init_card_mappings(struct drm_device *dev)
 
 static int nouveau_stub_init(struct drm_device *dev) { return 0; }
 static void nouveau_stub_takedown(struct drm_device *dev) {}
+static uint64_t nouveau_stub_timer_read(struct drm_device *dev) { return 0; }
+
 static int nouveau_init_engine_ptrs(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -104,6 +106,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->mc.init         = nv04_mc_init;
                engine->mc.takedown     = nv04_mc_takedown;
                engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
                engine->timer.takedown  = nv04_timer_takedown;
                engine->fb.init         = nv04_fb_init;
                engine->fb.takedown     = nv04_fb_takedown;
@@ -130,6 +133,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->mc.init         = nv04_mc_init;
                engine->mc.takedown     = nv04_mc_takedown;
                engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
                engine->timer.takedown  = nv04_timer_takedown;
                engine->fb.init         = nv10_fb_init;
                engine->fb.takedown     = nv10_fb_takedown;
@@ -156,6 +160,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->mc.init         = nv04_mc_init;
                engine->mc.takedown     = nv04_mc_takedown;
                engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
                engine->timer.takedown  = nv04_timer_takedown;
                engine->fb.init         = nv10_fb_init;
                engine->fb.takedown     = nv10_fb_takedown;
@@ -182,6 +187,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->mc.init         = nv04_mc_init;
                engine->mc.takedown     = nv04_mc_takedown;
                engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
                engine->timer.takedown  = nv04_timer_takedown;
                engine->fb.init         = nv10_fb_init;
                engine->fb.takedown     = nv10_fb_takedown;
@@ -208,6 +214,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->mc.init         = nv40_mc_init;
                engine->mc.takedown     = nv40_mc_takedown;
                engine->timer.init      = nv04_timer_init;
+               engine->timer.read      = nv04_timer_read;
                engine->timer.takedown  = nv04_timer_takedown;
                engine->fb.init         = nv40_fb_init;
                engine->fb.takedown     = nv40_fb_takedown;
@@ -235,6 +242,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->mc.init         = nv50_mc_init;
                engine->mc.takedown     = nv50_mc_takedown;
                engine->timer.init      = nouveau_stub_init;
+               engine->timer.read      = nouveau_stub_timer_read;
                engine->timer.takedown  = nouveau_stub_takedown;
                engine->fb.init         = nouveau_stub_init;
                engine->fb.takedown     = nouveau_stub_takedown;
index efe78da..08a27f4 100644 (file)
@@ -17,6 +17,27 @@ nv04_timer_init(struct drm_device *dev)
        return 0;
 }
 
+uint64_t
+nv04_timer_read(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       uint32_t low;
+       /* From kmmio dumps on nv28 this looks like how the blob does this.
+        * It reads the high dword twice, before and after.
+        * The only explanation seems to be that the 64-bit timer counter
+        * advances between high and low dword reads and may corrupt the
+        * result. Not confirmed.
+        */
+       uint32_t high2 = NV_READ(NV04_PTIMER_TIME_1);
+       uint32_t high1;
+       do {
+               high1 = high2;
+               low = NV_READ(NV04_PTIMER_TIME_0);
+               high2 = NV_READ(NV04_PTIMER_TIME_1);
+       } while(high1 != high2);
+       return (((uint64_t)high2) << 32) | (uint64_t)low;
+}
+
 void
 nv04_timer_takedown(struct drm_device *dev)
 {