Commit | Line | Data |
---|---|---|
6ee73861 BS |
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 | } |