diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_timer.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_timer.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_timer.c b/drivers/gpu/drm/nouveau/nv04_timer.c new file mode 100644 index 00000000000..1d09ddd5739 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv04_timer.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include "drmP.h" | ||
2 | #include "drm.h" | ||
3 | #include "nouveau_drv.h" | ||
4 | #include "nouveau_drm.h" | ||
5 | |||
6 | int | ||
7 | nv04_timer_init(struct drm_device *dev) | ||
8 | { | ||
9 | nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); | ||
10 | nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); | ||
11 | |||
12 | /* Just use the pre-existing values when possible for now; these regs | ||
13 | * are not written in nv (driver writer missed a /4 on the address), and | ||
14 | * writing 8 and 3 to the correct regs breaks the timings on the LVDS | ||
15 | * hardware sequencing microcode. | ||
16 | * A correct solution (involving calculations with the GPU PLL) can | ||
17 | * be done when kernel modesetting lands | ||
18 | */ | ||
19 | if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || | ||
20 | !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { | ||
21 | nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008); | ||
22 | nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003); | ||
23 | } | ||
24 | |||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | uint64_t | ||
29 | nv04_timer_read(struct drm_device *dev) | ||
30 | { | ||
31 | uint32_t low; | ||
32 | /* From kmmio dumps on nv28 this looks like how the blob does this. | ||
33 | * It reads the high dword twice, before and after. | ||
34 | * The only explanation seems to be that the 64-bit timer counter | ||
35 | * advances between high and low dword reads and may corrupt the | ||
36 | * result. Not confirmed. | ||
37 | */ | ||
38 | uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); | ||
39 | uint32_t high1; | ||
40 | do { | ||
41 | high1 = high2; | ||
42 | low = nv_rd32(dev, NV04_PTIMER_TIME_0); | ||
43 | high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); | ||
44 | } while (high1 != high2); | ||
45 | return (((uint64_t)high2) << 32) | (uint64_t)low; | ||
46 | } | ||
47 | |||
48 | void | ||
49 | nv04_timer_takedown(struct drm_device *dev) | ||
50 | { | ||
51 | } | ||