diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-09-26 21:18:14 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-10-04 19:57:54 -0400 |
commit | fade7ad56d929e168ead0f75e591468afa2fe97c (patch) | |
tree | 486c401dd30e8f3b5d35e97972822e81994cd446 | |
parent | aee582de806c7008756df23aa444c8e7d58004a9 (diff) |
drm/nva3: split pm backend out from nv50
This will end up quite different, it makes sense for it to be completely
separate.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_pm.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_pm.c | 56 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nva3_pm.c | 95 |
5 files changed, 137 insertions, 42 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index bdbde726778e..23fa82d667d6 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -10,7 +10,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ | 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ |
11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ | 11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ |
12 | nouveau_dp.o nouveau_ramht.o \ | 12 | nouveau_dp.o nouveau_ramht.o \ |
13 | nouveau_pm.o nouveau_volt.o nouveau_perf.o \ | 13 | nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ |
14 | nv04_timer.o \ | 14 | nv04_timer.o \ |
15 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 15 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
16 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ | 16 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ |
@@ -25,7 +25,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
25 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ | 25 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ |
26 | nv10_gpio.o nv50_gpio.o \ | 26 | nv10_gpio.o nv50_gpio.o \ |
27 | nv50_calc.o \ | 27 | nv50_calc.o \ |
28 | nv04_pm.o nv50_pm.o nouveau_temp.o | 28 | nv04_pm.o nv50_pm.o nva3_pm.o |
29 | 29 | ||
30 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o | 30 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o |
31 | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o | 31 | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h index babe64ac33c0..4a9838ddacec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h | |||
@@ -58,6 +58,12 @@ void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, | |||
58 | u32 id, int khz); | 58 | u32 id, int khz); |
59 | void nv50_pm_clock_set(struct drm_device *, void *); | 59 | void nv50_pm_clock_set(struct drm_device *, void *); |
60 | 60 | ||
61 | /* nva3_pm.c */ | ||
62 | int nva3_pm_clock_get(struct drm_device *, u32 id); | ||
63 | void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, | ||
64 | u32 id, int khz); | ||
65 | void nva3_pm_clock_set(struct drm_device *, void *); | ||
66 | |||
61 | /* nouveau_temp.c */ | 67 | /* nouveau_temp.c */ |
62 | void nouveau_temp_init(struct drm_device *dev); | 68 | void nouveau_temp_init(struct drm_device *dev); |
63 | void nouveau_temp_fini(struct drm_device *dev); | 69 | void nouveau_temp_fini(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index affcfc2fae19..75bce914e7b5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -375,9 +375,21 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
375 | engine->gpio.get = nv50_gpio_get; | 375 | engine->gpio.get = nv50_gpio_get; |
376 | engine->gpio.set = nv50_gpio_set; | 376 | engine->gpio.set = nv50_gpio_set; |
377 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | 377 | engine->gpio.irq_enable = nv50_gpio_irq_enable; |
378 | engine->pm.clock_get = nv50_pm_clock_get; | 378 | switch (dev_priv->chipset) { |
379 | engine->pm.clock_pre = nv50_pm_clock_pre; | 379 | case 0xa3: |
380 | engine->pm.clock_set = nv50_pm_clock_set; | 380 | case 0xa5: |
381 | case 0xa8: | ||
382 | case 0xaf: | ||
383 | engine->pm.clock_get = nva3_pm_clock_get; | ||
384 | engine->pm.clock_pre = nva3_pm_clock_pre; | ||
385 | engine->pm.clock_set = nva3_pm_clock_set; | ||
386 | break; | ||
387 | default: | ||
388 | engine->pm.clock_get = nv50_pm_clock_get; | ||
389 | engine->pm.clock_pre = nv50_pm_clock_pre; | ||
390 | engine->pm.clock_set = nv50_pm_clock_set; | ||
391 | break; | ||
392 | } | ||
381 | engine->pm.voltage_get = nouveau_voltage_gpio_get; | 393 | engine->pm.voltage_get = nouveau_voltage_gpio_get; |
382 | engine->pm.voltage_set = nouveau_voltage_gpio_set; | 394 | engine->pm.voltage_set = nouveau_voltage_gpio_set; |
383 | if (dev_priv->chipset >= 0x84) | 395 | if (dev_priv->chipset >= 0x84) |
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 2a9fabdf1b75..7dbb305d7e63 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c | |||
@@ -27,12 +27,6 @@ | |||
27 | #include "nouveau_bios.h" | 27 | #include "nouveau_bios.h" |
28 | #include "nouveau_pm.h" | 28 | #include "nouveau_pm.h" |
29 | 29 | ||
30 | /*XXX: boards using limits 0x40 need fixing, the register layout | ||
31 | * is correct here, but, there's some other funny magic | ||
32 | * that modifies things, so it's not likely we'll set/read | ||
33 | * the correct timings yet.. working on it... | ||
34 | */ | ||
35 | |||
36 | struct nv50_pm_state { | 30 | struct nv50_pm_state { |
37 | struct nouveau_pm_level *perflvl; | 31 | struct nouveau_pm_level *perflvl; |
38 | struct pll_lims pll; | 32 | struct pll_lims pll; |
@@ -51,21 +45,13 @@ nv50_pm_clock_get(struct drm_device *dev, u32 id) | |||
51 | if (ret) | 45 | if (ret) |
52 | return ret; | 46 | return ret; |
53 | 47 | ||
54 | if (pll.vco2.maxfreq) { | 48 | reg0 = nv_rd32(dev, pll.reg + 0); |
55 | reg0 = nv_rd32(dev, pll.reg + 0); | 49 | reg1 = nv_rd32(dev, pll.reg + 4); |
56 | reg1 = nv_rd32(dev, pll.reg + 4); | 50 | P = (reg0 & 0x00070000) >> 16; |
57 | P = (reg0 & 0x00070000) >> 16; | 51 | N = (reg1 & 0x0000ff00) >> 8; |
58 | N = (reg1 & 0x0000ff00) >> 8; | 52 | M = (reg1 & 0x000000ff); |
59 | M = (reg1 & 0x000000ff); | ||
60 | |||
61 | return ((pll.refclk * N / M) >> P); | ||
62 | } | ||
63 | 53 | ||
64 | reg0 = nv_rd32(dev, pll.reg + 4); | 54 | return ((pll.refclk * N / M) >> P); |
65 | P = (reg0 & 0x003f0000) >> 16; | ||
66 | N = (reg0 & 0x0000ff00) >> 8; | ||
67 | M = (reg0 & 0x000000ff); | ||
68 | return pll.refclk * N / M / P; | ||
69 | } | 55 | } |
70 | 56 | ||
71 | void * | 57 | void * |
@@ -125,23 +111,19 @@ nv50_pm_clock_set(struct drm_device *dev, void *pre_state) | |||
125 | nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); | 111 | nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); |
126 | } | 112 | } |
127 | 113 | ||
128 | if (state->pll.vco2.maxfreq) { | 114 | if (state->type == PLL_MEMORY) { |
129 | if (state->type == PLL_MEMORY) { | 115 | nv_wr32(dev, 0x100210, 0); |
130 | nv_wr32(dev, 0x100210, 0); | 116 | nv_wr32(dev, 0x1002dc, 1); |
131 | nv_wr32(dev, 0x1002dc, 1); | 117 | } |
132 | } | 118 | |
133 | 119 | tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; | |
134 | tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; | 120 | tmp |= 0x80000000 | (P << 16); |
135 | tmp |= 0x80000000 | (P << 16); | 121 | nv_wr32(dev, reg + 0, tmp); |
136 | nv_wr32(dev, reg + 0, tmp); | 122 | nv_wr32(dev, reg + 4, (N << 8) | M); |
137 | nv_wr32(dev, reg + 4, (N << 8) | M); | 123 | |
138 | 124 | if (state->type == PLL_MEMORY) { | |
139 | if (state->type == PLL_MEMORY) { | 125 | nv_wr32(dev, 0x1002dc, 0); |
140 | nv_wr32(dev, 0x1002dc, 0); | 126 | nv_wr32(dev, 0x100210, 0x80000000); |
141 | nv_wr32(dev, 0x100210, 0x80000000); | ||
142 | } | ||
143 | } else { | ||
144 | nv_wr32(dev, reg + 4, (P << 16) | (N << 8) | M); | ||
145 | } | 127 | } |
146 | 128 | ||
147 | kfree(state); | 129 | kfree(state); |
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c new file mode 100644 index 000000000000..dbbafed36406 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nva3_pm.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | #include "nouveau_drv.h" | ||
27 | #include "nouveau_bios.h" | ||
28 | #include "nouveau_pm.h" | ||
29 | |||
30 | /*XXX: boards using limits 0x40 need fixing, the register layout | ||
31 | * is correct here, but, there's some other funny magic | ||
32 | * that modifies things, so it's not likely we'll set/read | ||
33 | * the correct timings yet.. working on it... | ||
34 | */ | ||
35 | |||
36 | struct nva3_pm_state { | ||
37 | struct pll_lims pll; | ||
38 | int N, M, P; | ||
39 | }; | ||
40 | |||
41 | int | ||
42 | nva3_pm_clock_get(struct drm_device *dev, u32 id) | ||
43 | { | ||
44 | struct pll_lims pll; | ||
45 | int P, N, M, ret; | ||
46 | u32 reg; | ||
47 | |||
48 | ret = get_pll_limits(dev, id, &pll); | ||
49 | if (ret) | ||
50 | return ret; | ||
51 | |||
52 | reg = nv_rd32(dev, pll.reg + 4); | ||
53 | P = (reg & 0x003f0000) >> 16; | ||
54 | N = (reg & 0x0000ff00) >> 8; | ||
55 | M = (reg & 0x000000ff); | ||
56 | return pll.refclk * N / M / P; | ||
57 | } | ||
58 | |||
59 | void * | ||
60 | nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||
61 | u32 id, int khz) | ||
62 | { | ||
63 | struct nva3_pm_state *state; | ||
64 | int dummy, ret; | ||
65 | |||
66 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
67 | if (!state) | ||
68 | return ERR_PTR(-ENOMEM); | ||
69 | |||
70 | ret = get_pll_limits(dev, id, &state->pll); | ||
71 | if (ret < 0) { | ||
72 | kfree(state); | ||
73 | return (ret == -ENOENT) ? NULL : ERR_PTR(ret); | ||
74 | } | ||
75 | |||
76 | ret = nv50_calc_pll2(dev, &state->pll, khz, &state->N, &dummy, | ||
77 | &state->M, &state->P); | ||
78 | if (ret < 0) { | ||
79 | kfree(state); | ||
80 | return ERR_PTR(ret); | ||
81 | } | ||
82 | |||
83 | return state; | ||
84 | } | ||
85 | |||
86 | void | ||
87 | nva3_pm_clock_set(struct drm_device *dev, void *pre_state) | ||
88 | { | ||
89 | struct nva3_pm_state *state = pre_state; | ||
90 | u32 reg = state->pll.reg; | ||
91 | |||
92 | nv_wr32(dev, reg + 4, (state->P << 16) | (state->N << 8) | state->M); | ||
93 | kfree(state); | ||
94 | } | ||
95 | |||