diff options
28 files changed, 1328 insertions, 1213 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 2964d71d3996..2574fd35122a 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -23,11 +23,14 @@ nouveau-y += core/subdev/bios/bit.o | |||
23 | nouveau-y += core/subdev/bios/dcb.o | 23 | nouveau-y += core/subdev/bios/dcb.o |
24 | nouveau-y += core/subdev/bios/gpio.o | 24 | nouveau-y += core/subdev/bios/gpio.o |
25 | nouveau-y += core/subdev/bios/i2c.o | 25 | nouveau-y += core/subdev/bios/i2c.o |
26 | nouveau-y += core/subdev/bios/pll.o | ||
26 | nouveau-y += core/subdev/clock/nv04.o | 27 | nouveau-y += core/subdev/clock/nv04.o |
27 | nouveau-y += core/subdev/clock/nv40.o | 28 | nouveau-y += core/subdev/clock/nv40.o |
28 | nouveau-y += core/subdev/clock/nv50.o | 29 | nouveau-y += core/subdev/clock/nv50.o |
29 | nouveau-y += core/subdev/clock/nva3.o | 30 | nouveau-y += core/subdev/clock/nva3.o |
30 | nouveau-y += core/subdev/clock/nvc0.o | 31 | nouveau-y += core/subdev/clock/nvc0.o |
32 | nouveau-y += core/subdev/clock/pllnv04.o | ||
33 | nouveau-y += core/subdev/clock/pllnva3.o | ||
31 | nouveau-y += core/subdev/device/base.o | 34 | nouveau-y += core/subdev/device/base.o |
32 | nouveau-y += core/subdev/device/nv04.o | 35 | nouveau-y += core/subdev/device/nv04.o |
33 | nouveau-y += core/subdev/device/nv10.o | 36 | nouveau-y += core/subdev/device/nv10.o |
@@ -114,7 +117,6 @@ nouveau-y += nouveau_drm.o nouveau_compat.o \ | |||
114 | nv50_cursor.o nv50_display.o \ | 117 | nv50_cursor.o nv50_display.o \ |
115 | nvd0_display.o \ | 118 | nvd0_display.o \ |
116 | nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ | 119 | nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ |
117 | nv50_calc.o \ | ||
118 | nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ | 120 | nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ |
119 | nouveau_prime.o | 121 | nouveau_prime.o |
120 | 122 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h new file mode 100644 index 000000000000..c345097592f2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef __NVBIOS_PLL_H__ | ||
2 | #define __NVBIOS_PLL_H__ | ||
3 | |||
4 | /*XXX: kill me */ | ||
5 | struct nouveau_pll_vals { | ||
6 | union { | ||
7 | struct { | ||
8 | #ifdef __BIG_ENDIAN | ||
9 | uint8_t N1, M1, N2, M2; | ||
10 | #else | ||
11 | uint8_t M1, N1, M2, N2; | ||
12 | #endif | ||
13 | }; | ||
14 | struct { | ||
15 | uint16_t NM1, NM2; | ||
16 | } __attribute__((packed)); | ||
17 | }; | ||
18 | int log2P; | ||
19 | |||
20 | int refclk; | ||
21 | }; | ||
22 | |||
23 | struct nouveau_bios; | ||
24 | |||
25 | /* these match types in pll limits table version 0x40, | ||
26 | * nouveau uses them on all chipsets internally where a | ||
27 | * specific pll needs to be referenced, but the exact | ||
28 | * register isn't known. | ||
29 | */ | ||
30 | enum nvbios_pll_type { | ||
31 | PLL_CORE = 0x01, | ||
32 | PLL_SHADER = 0x02, | ||
33 | PLL_UNK03 = 0x03, | ||
34 | PLL_MEMORY = 0x04, | ||
35 | PLL_VDEC = 0x05, | ||
36 | PLL_UNK40 = 0x40, | ||
37 | PLL_UNK41 = 0x41, | ||
38 | PLL_UNK42 = 0x42, | ||
39 | PLL_VPLL0 = 0x80, | ||
40 | PLL_VPLL1 = 0x81, | ||
41 | PLL_MAX = 0xff | ||
42 | }; | ||
43 | |||
44 | struct nvbios_pll { | ||
45 | enum nvbios_pll_type type; | ||
46 | u32 reg; | ||
47 | u32 refclk; | ||
48 | |||
49 | u8 min_p; | ||
50 | u8 max_p; | ||
51 | u8 bias_p; | ||
52 | |||
53 | /* | ||
54 | * for most pre nv50 cards setting a log2P of 7 (the common max_log2p | ||
55 | * value) is no different to 6 (at least for vplls) so allowing the MNP | ||
56 | * calc to use 7 causes the generated clock to be out by a factor of 2. | ||
57 | * however, max_log2p cannot be fixed-up during parsing as the | ||
58 | * unmodified max_log2p value is still needed for setting mplls, hence | ||
59 | * an additional max_usable_log2p member | ||
60 | */ | ||
61 | u8 max_p_usable; | ||
62 | |||
63 | struct { | ||
64 | u32 min_freq; | ||
65 | u32 max_freq; | ||
66 | u32 min_inputfreq; | ||
67 | u32 max_inputfreq; | ||
68 | u8 min_m; | ||
69 | u8 max_m; | ||
70 | u8 min_n; | ||
71 | u8 max_n; | ||
72 | } vco1, vco2; | ||
73 | }; | ||
74 | |||
75 | int nvbios_pll_parse(struct nouveau_bios *, u32 type, struct nvbios_pll *); | ||
76 | |||
77 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 137c4598a1b6..39e73b91d360 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h | |||
@@ -4,9 +4,21 @@ | |||
4 | #include <core/device.h> | 4 | #include <core/device.h> |
5 | #include <core/subdev.h> | 5 | #include <core/subdev.h> |
6 | 6 | ||
7 | struct nouveau_pll_vals; | ||
8 | struct nvbios_pll; | ||
9 | |||
7 | struct nouveau_clock { | 10 | struct nouveau_clock { |
8 | struct nouveau_subdev base; | 11 | struct nouveau_subdev base; |
9 | void (*pll_set)(struct nouveau_clock *, u32 type, u32 freq); | 12 | |
13 | int (*pll_set)(struct nouveau_clock *, u32 type, u32 freq); | ||
14 | |||
15 | /*XXX: die, these are here *only* to support the completely | ||
16 | * bat-shit insane what-was-nouveau_hw.c code | ||
17 | */ | ||
18 | int (*pll_calc)(struct nouveau_clock *, struct nvbios_pll *, | ||
19 | int clk, struct nouveau_pll_vals *pv); | ||
20 | int (*pll_prog)(struct nouveau_clock *, u32 reg1, | ||
21 | struct nouveau_pll_vals *pv); | ||
10 | }; | 22 | }; |
11 | 23 | ||
12 | static inline struct nouveau_clock * | 24 | static inline struct nouveau_clock * |
@@ -37,4 +49,11 @@ extern struct nouveau_oclass nv50_clock_oclass; | |||
37 | extern struct nouveau_oclass nva3_clock_oclass; | 49 | extern struct nouveau_oclass nva3_clock_oclass; |
38 | extern struct nouveau_oclass nvc0_clock_oclass; | 50 | extern struct nouveau_oclass nvc0_clock_oclass; |
39 | 51 | ||
52 | int nv04_clock_pll_set(struct nouveau_clock *, u32 type, u32 freq); | ||
53 | int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, | ||
54 | int clk, struct nouveau_pll_vals *); | ||
55 | int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, | ||
56 | struct nouveau_pll_vals *); | ||
57 | |||
58 | |||
40 | #endif | 59 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h index d81df1ae442d..fee09ad818e4 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vga.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vga.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __NOUVEAU_VGA_H__ | 1 | #ifndef __NOUVEAU_VGA_H__ |
2 | #define __NOUVEAU_VGA_H__ | 2 | #define __NOUVEAU_VGA_H__ |
3 | 3 | ||
4 | #include <core/os.h> | ||
5 | |||
4 | /* access to various legacy io ports */ | 6 | /* access to various legacy io ports */ |
5 | u8 nv_rdport(void *obj, int head, u16 port); | 7 | u8 nv_rdport(void *obj, int head, u16 port); |
6 | void nv_wrport(void *obj, int head, u16 port, u8 value); | 8 | void nv_wrport(void *obj, int head, u16 port, u8 value); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c new file mode 100644 index 000000000000..5e5f4cddae3c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c | |||
@@ -0,0 +1,417 @@ | |||
1 | /* | ||
2 | * Copyright 2005-2006 Erik Waling | ||
3 | * Copyright 2006 Stephane Marchesin | ||
4 | * Copyright 2007-2009 Stuart Bennett | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in | ||
14 | * all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||
21 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | * SOFTWARE. | ||
23 | */ | ||
24 | |||
25 | #include <subdev/vga.h> | ||
26 | #include <subdev/bios.h> | ||
27 | #include <subdev/bios/bit.h> | ||
28 | #include <subdev/bios/bmp.h> | ||
29 | #include <subdev/bios/pll.h> | ||
30 | |||
31 | struct pll_mapping { | ||
32 | u8 type; | ||
33 | u32 reg; | ||
34 | }; | ||
35 | |||
36 | static struct pll_mapping | ||
37 | nv04_pll_mapping[] = { | ||
38 | { PLL_CORE , 0x680500 }, | ||
39 | { PLL_MEMORY, 0x680504 }, | ||
40 | { PLL_VPLL0 , 0x680508 }, | ||
41 | { PLL_VPLL1 , 0x680520 }, | ||
42 | {} | ||
43 | }; | ||
44 | |||
45 | static struct pll_mapping | ||
46 | nv40_pll_mapping[] = { | ||
47 | { PLL_CORE , 0x004000 }, | ||
48 | { PLL_MEMORY, 0x004020 }, | ||
49 | { PLL_VPLL0 , 0x680508 }, | ||
50 | { PLL_VPLL1 , 0x680520 }, | ||
51 | {} | ||
52 | }; | ||
53 | |||
54 | static struct pll_mapping | ||
55 | nv50_pll_mapping[] = { | ||
56 | { PLL_CORE , 0x004028 }, | ||
57 | { PLL_SHADER, 0x004020 }, | ||
58 | { PLL_UNK03 , 0x004000 }, | ||
59 | { PLL_MEMORY, 0x004008 }, | ||
60 | { PLL_UNK40 , 0x00e810 }, | ||
61 | { PLL_UNK41 , 0x00e818 }, | ||
62 | { PLL_UNK42 , 0x00e824 }, | ||
63 | { PLL_VPLL0 , 0x614100 }, | ||
64 | { PLL_VPLL1 , 0x614900 }, | ||
65 | {} | ||
66 | }; | ||
67 | |||
68 | static struct pll_mapping | ||
69 | nv84_pll_mapping[] = { | ||
70 | { PLL_CORE , 0x004028 }, | ||
71 | { PLL_SHADER, 0x004020 }, | ||
72 | { PLL_MEMORY, 0x004008 }, | ||
73 | { PLL_VDEC , 0x004030 }, | ||
74 | { PLL_UNK41 , 0x00e818 }, | ||
75 | { PLL_VPLL0 , 0x614100 }, | ||
76 | { PLL_VPLL1 , 0x614900 }, | ||
77 | {} | ||
78 | }; | ||
79 | |||
80 | static u16 | ||
81 | pll_limits_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | ||
82 | { | ||
83 | struct bit_entry bit_C; | ||
84 | |||
85 | if (!bit_entry(bios, 'C', &bit_C) && bit_C.length >= 10) { | ||
86 | u16 data = nv_ro16(bios, bit_C.offset + 8); | ||
87 | if (data) { | ||
88 | *ver = nv_ro08(bios, data + 0); | ||
89 | *hdr = nv_ro08(bios, data + 1); | ||
90 | *len = nv_ro08(bios, data + 2); | ||
91 | *cnt = nv_ro08(bios, data + 3); | ||
92 | return data; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | if (bmp_version(bios) >= 0x0524) { | ||
97 | u16 data = nv_ro16(bios, bios->bmp_offset + 142); | ||
98 | if (data) { | ||
99 | *ver = nv_ro08(bios, data + 0); | ||
100 | *hdr = 1; | ||
101 | *cnt = 1; | ||
102 | *len = 0x18; | ||
103 | return data; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | *ver = 0x00; | ||
108 | return 0x0000; | ||
109 | } | ||
110 | |||
111 | static struct pll_mapping * | ||
112 | pll_map(struct nouveau_bios *bios) | ||
113 | { | ||
114 | switch (nv_device(bios)->card_type) { | ||
115 | case NV_04: | ||
116 | case NV_10: | ||
117 | case NV_20: | ||
118 | case NV_30: | ||
119 | return nv04_pll_mapping; | ||
120 | break; | ||
121 | case NV_40: | ||
122 | return nv40_pll_mapping; | ||
123 | case NV_50: | ||
124 | if (nv_device(bios)->chipset == 0x50) | ||
125 | return nv50_pll_mapping; | ||
126 | else | ||
127 | if (nv_device(bios)->chipset < 0xa3 || | ||
128 | nv_device(bios)->chipset == 0xaa || | ||
129 | nv_device(bios)->chipset == 0xac) | ||
130 | return nv84_pll_mapping; | ||
131 | default: | ||
132 | return NULL; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | static u16 | ||
137 | pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) | ||
138 | { | ||
139 | struct pll_mapping *map; | ||
140 | u8 hdr, cnt; | ||
141 | u16 data; | ||
142 | |||
143 | data = pll_limits_table(bios, ver, &hdr, &cnt, len); | ||
144 | if (data && *ver >= 0x30) { | ||
145 | data += hdr; | ||
146 | while (cnt--) { | ||
147 | if (nv_ro32(bios, data + 3) == reg) { | ||
148 | *type = nv_ro08(bios, data + 0); | ||
149 | return data; | ||
150 | } | ||
151 | data += *len; | ||
152 | } | ||
153 | return 0x0000; | ||
154 | } | ||
155 | |||
156 | map = pll_map(bios); | ||
157 | while (map->reg) { | ||
158 | if (map->reg == reg && *ver >= 0x20) { | ||
159 | u16 addr = (data += hdr); | ||
160 | while (cnt--) { | ||
161 | if (nv_ro32(bios, data) == map->reg) { | ||
162 | *type = map->type; | ||
163 | return data; | ||
164 | } | ||
165 | data += *len; | ||
166 | } | ||
167 | return addr; | ||
168 | } else | ||
169 | if (map->reg == reg) { | ||
170 | *type = map->type; | ||
171 | return data + 1; | ||
172 | } | ||
173 | map++; | ||
174 | } | ||
175 | |||
176 | return 0x0000; | ||
177 | } | ||
178 | |||
179 | static u16 | ||
180 | pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) | ||
181 | { | ||
182 | struct pll_mapping *map; | ||
183 | u8 hdr, cnt; | ||
184 | u16 data; | ||
185 | |||
186 | data = pll_limits_table(bios, ver, &hdr, &cnt, len); | ||
187 | if (data && *ver >= 0x30) { | ||
188 | data += hdr; | ||
189 | while (cnt--) { | ||
190 | if (nv_ro08(bios, data + 0) == type) { | ||
191 | *reg = nv_ro32(bios, data + 3); | ||
192 | return data; | ||
193 | } | ||
194 | data += *len; | ||
195 | } | ||
196 | return 0x0000; | ||
197 | } | ||
198 | |||
199 | map = pll_map(bios); | ||
200 | while (map->reg) { | ||
201 | if (map->type == type && *ver >= 0x20) { | ||
202 | u16 addr = (data += hdr); | ||
203 | while (cnt--) { | ||
204 | if (nv_ro32(bios, data) == map->reg) { | ||
205 | *reg = map->reg; | ||
206 | return data; | ||
207 | } | ||
208 | data += *len; | ||
209 | } | ||
210 | return addr; | ||
211 | } else | ||
212 | if (map->type == type) { | ||
213 | *reg = map->reg; | ||
214 | return data + 1; | ||
215 | } | ||
216 | map++; | ||
217 | } | ||
218 | |||
219 | return 0x0000; | ||
220 | } | ||
221 | |||
222 | int | ||
223 | nvbios_pll_parse(struct nouveau_bios *bios, u32 type, struct nvbios_pll *info) | ||
224 | { | ||
225 | u8 ver, len; | ||
226 | u32 reg = type; | ||
227 | u16 data; | ||
228 | |||
229 | if (type > PLL_MAX) { | ||
230 | reg = type; | ||
231 | data = pll_map_reg(bios, reg, &type, &ver, &len); | ||
232 | } else { | ||
233 | data = pll_map_type(bios, type, ®, &ver, &len); | ||
234 | } | ||
235 | |||
236 | if (ver && !data) | ||
237 | return -ENOENT; | ||
238 | |||
239 | memset(info, 0, sizeof(*info)); | ||
240 | info->type = type; | ||
241 | info->reg = reg; | ||
242 | |||
243 | switch (ver) { | ||
244 | case 0x00: | ||
245 | break; | ||
246 | case 0x10: | ||
247 | case 0x11: | ||
248 | info->vco1.min_freq = nv_ro32(bios, data + 0); | ||
249 | info->vco1.max_freq = nv_ro32(bios, data + 4); | ||
250 | info->vco2.min_freq = nv_ro32(bios, data + 8); | ||
251 | info->vco2.max_freq = nv_ro32(bios, data + 12); | ||
252 | info->vco1.min_inputfreq = nv_ro32(bios, data + 16); | ||
253 | info->vco2.min_inputfreq = nv_ro32(bios, data + 20); | ||
254 | info->vco1.max_inputfreq = INT_MAX; | ||
255 | info->vco2.max_inputfreq = INT_MAX; | ||
256 | |||
257 | info->max_p = 0x7; | ||
258 | info->max_p_usable = 0x6; | ||
259 | |||
260 | /* these values taken from nv30/31/36 */ | ||
261 | switch (bios->version.chip) { | ||
262 | case 0x36: | ||
263 | info->vco1.min_n = 0x5; | ||
264 | break; | ||
265 | default: | ||
266 | info->vco1.min_n = 0x1; | ||
267 | break; | ||
268 | } | ||
269 | info->vco1.max_n = 0xff; | ||
270 | info->vco1.min_m = 0x1; | ||
271 | info->vco1.max_m = 0xd; | ||
272 | |||
273 | /* | ||
274 | * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this | ||
275 | * table version (apart from nv35)), N2 is compared to | ||
276 | * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and | ||
277 | * save a comparison | ||
278 | */ | ||
279 | info->vco2.min_n = 0x4; | ||
280 | switch (bios->version.chip) { | ||
281 | case 0x30: | ||
282 | case 0x35: | ||
283 | info->vco2.max_n = 0x1f; | ||
284 | break; | ||
285 | default: | ||
286 | info->vco2.max_n = 0x28; | ||
287 | break; | ||
288 | } | ||
289 | info->vco2.min_m = 0x1; | ||
290 | info->vco2.max_m = 0x4; | ||
291 | break; | ||
292 | case 0x20: | ||
293 | case 0x21: | ||
294 | info->vco1.min_freq = nv_ro16(bios, data + 4) * 1000; | ||
295 | info->vco1.max_freq = nv_ro16(bios, data + 6) * 1000; | ||
296 | info->vco2.min_freq = nv_ro16(bios, data + 8) * 1000; | ||
297 | info->vco2.max_freq = nv_ro16(bios, data + 10) * 1000; | ||
298 | info->vco1.min_inputfreq = nv_ro16(bios, data + 12) * 1000; | ||
299 | info->vco2.min_inputfreq = nv_ro16(bios, data + 14) * 1000; | ||
300 | info->vco1.max_inputfreq = nv_ro16(bios, data + 16) * 1000; | ||
301 | info->vco2.max_inputfreq = nv_ro16(bios, data + 18) * 1000; | ||
302 | info->vco1.min_n = nv_ro08(bios, data + 20); | ||
303 | info->vco1.max_n = nv_ro08(bios, data + 21); | ||
304 | info->vco1.min_m = nv_ro08(bios, data + 22); | ||
305 | info->vco1.max_m = nv_ro08(bios, data + 23); | ||
306 | info->vco2.min_n = nv_ro08(bios, data + 24); | ||
307 | info->vco2.max_n = nv_ro08(bios, data + 25); | ||
308 | info->vco2.min_m = nv_ro08(bios, data + 26); | ||
309 | info->vco2.max_m = nv_ro08(bios, data + 27); | ||
310 | |||
311 | info->max_p = nv_ro08(bios, data + 29); | ||
312 | info->max_p_usable = info->max_p; | ||
313 | if (bios->version.chip < 0x60) | ||
314 | info->max_p_usable = 0x6; | ||
315 | info->bias_p = nv_ro08(bios, data + 30); | ||
316 | |||
317 | if (len > 0x22) | ||
318 | info->refclk = nv_ro32(bios, data + 31); | ||
319 | break; | ||
320 | case 0x30: | ||
321 | data = nv_ro16(bios, data + 1); | ||
322 | |||
323 | info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; | ||
324 | info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; | ||
325 | info->vco2.min_freq = nv_ro16(bios, data + 4) * 1000; | ||
326 | info->vco2.max_freq = nv_ro16(bios, data + 6) * 1000; | ||
327 | info->vco1.min_inputfreq = nv_ro16(bios, data + 8) * 1000; | ||
328 | info->vco2.min_inputfreq = nv_ro16(bios, data + 10) * 1000; | ||
329 | info->vco1.max_inputfreq = nv_ro16(bios, data + 12) * 1000; | ||
330 | info->vco2.max_inputfreq = nv_ro16(bios, data + 14) * 1000; | ||
331 | info->vco1.min_n = nv_ro08(bios, data + 16); | ||
332 | info->vco1.max_n = nv_ro08(bios, data + 17); | ||
333 | info->vco1.min_m = nv_ro08(bios, data + 18); | ||
334 | info->vco1.max_m = nv_ro08(bios, data + 19); | ||
335 | info->vco2.min_n = nv_ro08(bios, data + 20); | ||
336 | info->vco2.max_n = nv_ro08(bios, data + 21); | ||
337 | info->vco2.min_m = nv_ro08(bios, data + 22); | ||
338 | info->vco2.max_m = nv_ro08(bios, data + 23); | ||
339 | info->max_p_usable = info->max_p = nv_ro08(bios, data + 25); | ||
340 | info->bias_p = nv_ro08(bios, data + 27); | ||
341 | info->refclk = nv_ro32(bios, data + 28); | ||
342 | break; | ||
343 | case 0x40: | ||
344 | info->refclk = nv_ro16(bios, data + 9) * 1000; | ||
345 | data = nv_ro16(bios, data + 1); | ||
346 | |||
347 | info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; | ||
348 | info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; | ||
349 | info->vco1.min_inputfreq = nv_ro16(bios, data + 4) * 1000; | ||
350 | info->vco1.max_inputfreq = nv_ro16(bios, data + 6) * 1000; | ||
351 | info->vco1.min_m = nv_ro08(bios, data + 8); | ||
352 | info->vco1.max_m = nv_ro08(bios, data + 9); | ||
353 | info->vco1.min_n = nv_ro08(bios, data + 10); | ||
354 | info->vco1.max_n = nv_ro08(bios, data + 11); | ||
355 | info->min_p = nv_ro08(bios, data + 12); | ||
356 | info->max_p = nv_ro08(bios, data + 13); | ||
357 | break; | ||
358 | default: | ||
359 | nv_error(bios, "unknown pll limits version 0x%02x\n", ver); | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | |||
363 | if (!info->refclk) { | ||
364 | info->refclk = nv_device(bios)->crystal; | ||
365 | if (bios->version.chip == 0x51) { | ||
366 | u32 sel_clk = nv_rd32(bios, 0x680524); | ||
367 | if ((info->reg == 0x680508 && sel_clk & 0x20) || | ||
368 | (info->reg == 0x680520 && sel_clk & 0x80)) { | ||
369 | if (nv_rdvgac(bios, 0, 0x27) < 0xa3) | ||
370 | info->refclk = 200000; | ||
371 | else | ||
372 | info->refclk = 25000; | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | |||
377 | /* | ||
378 | * By now any valid limit table ought to have set a max frequency for | ||
379 | * vco1, so if it's zero it's either a pre limit table bios, or one | ||
380 | * with an empty limit table (seen on nv18) | ||
381 | */ | ||
382 | if (!info->vco1.max_freq) { | ||
383 | info->vco1.max_freq = nv_ro32(bios, bios->bmp_offset + 67); | ||
384 | info->vco1.min_freq = nv_ro32(bios, bios->bmp_offset + 71); | ||
385 | if (bmp_version(bios) < 0x0506) { | ||
386 | info->vco1.max_freq = 256000; | ||
387 | info->vco1.min_freq = 128000; | ||
388 | } | ||
389 | |||
390 | info->vco1.min_inputfreq = 0; | ||
391 | info->vco1.max_inputfreq = INT_MAX; | ||
392 | info->vco1.min_n = 0x1; | ||
393 | info->vco1.max_n = 0xff; | ||
394 | info->vco1.min_m = 0x1; | ||
395 | |||
396 | if (nv_device(bios)->crystal == 13500) { | ||
397 | /* nv05 does this, nv11 doesn't, nv10 unknown */ | ||
398 | if (bios->version.chip < 0x11) | ||
399 | info->vco1.min_m = 0x7; | ||
400 | info->vco1.max_m = 0xd; | ||
401 | } else { | ||
402 | if (bios->version.chip < 0x11) | ||
403 | info->vco1.min_m = 0x8; | ||
404 | info->vco1.max_m = 0xe; | ||
405 | } | ||
406 | |||
407 | if (bios->version.chip < 0x17 || | ||
408 | bios->version.chip == 0x1a || | ||
409 | bios->version.chip == 0x20) | ||
410 | info->max_p = 4; | ||
411 | else | ||
412 | info->max_p = 5; | ||
413 | info->max_p_usable = info->max_p; | ||
414 | } | ||
415 | |||
416 | return 0; | ||
417 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c index 3a3b3b149690..b7fd1151166e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c | |||
@@ -23,17 +23,309 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/clock.h> | 25 | #include <subdev/clock.h> |
26 | #include <subdev/bios.h> | ||
27 | #include <subdev/bios/pll.h> | ||
28 | |||
29 | #include "pll.h" | ||
26 | 30 | ||
27 | struct nv04_clock_priv { | 31 | struct nv04_clock_priv { |
28 | struct nouveau_clock base; | 32 | struct nouveau_clock base; |
29 | }; | 33 | }; |
30 | 34 | ||
35 | static int | ||
36 | powerctrl_1_shift(int chip_version, int reg) | ||
37 | { | ||
38 | int shift = -4; | ||
39 | |||
40 | if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20) | ||
41 | return shift; | ||
42 | |||
43 | switch (reg) { | ||
44 | case 0x680520: | ||
45 | shift += 4; | ||
46 | case 0x680508: | ||
47 | shift += 4; | ||
48 | case 0x680504: | ||
49 | shift += 4; | ||
50 | case 0x680500: | ||
51 | shift += 4; | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * the shift for vpll regs is only used for nv3x chips with a single | ||
56 | * stage pll | ||
57 | */ | ||
58 | if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 || | ||
59 | chip_version == 0x36 || chip_version >= 0x40)) | ||
60 | shift = -4; | ||
61 | |||
62 | return shift; | ||
63 | } | ||
64 | |||
31 | static void | 65 | static void |
66 | setPLL_single(struct nv04_clock_priv *priv, u32 reg, | ||
67 | struct nouveau_pll_vals *pv) | ||
68 | { | ||
69 | int chip_version = nouveau_bios(priv)->version.chip; | ||
70 | uint32_t oldpll = nv_rd32(priv, reg); | ||
71 | int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; | ||
72 | uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; | ||
73 | uint32_t saved_powerctrl_1 = 0; | ||
74 | int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg); | ||
75 | |||
76 | if (oldpll == pll) | ||
77 | return; /* already set */ | ||
78 | |||
79 | if (shift_powerctrl_1 >= 0) { | ||
80 | saved_powerctrl_1 = nv_rd32(priv, 0x001584); | ||
81 | nv_wr32(priv, 0x001584, | ||
82 | (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | | ||
83 | 1 << shift_powerctrl_1); | ||
84 | } | ||
85 | |||
86 | if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) | ||
87 | /* upclock -- write new post divider first */ | ||
88 | nv_wr32(priv, reg, pv->log2P << 16 | (oldpll & 0xffff)); | ||
89 | else | ||
90 | /* downclock -- write new NM first */ | ||
91 | nv_wr32(priv, reg, (oldpll & 0xffff0000) | pv->NM1); | ||
92 | |||
93 | if (chip_version < 0x17 && chip_version != 0x11) | ||
94 | /* wait a bit on older chips */ | ||
95 | msleep(64); | ||
96 | nv_rd32(priv, reg); | ||
97 | |||
98 | /* then write the other half as well */ | ||
99 | nv_wr32(priv, reg, pll); | ||
100 | |||
101 | if (shift_powerctrl_1 >= 0) | ||
102 | nv_wr32(priv, 0x001584, saved_powerctrl_1); | ||
103 | } | ||
104 | |||
105 | static uint32_t | ||
106 | new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) | ||
107 | { | ||
108 | bool head_a = (reg1 == 0x680508); | ||
109 | |||
110 | if (ss) /* single stage pll mode */ | ||
111 | ramdac580 |= head_a ? 0x00000100 : 0x10000000; | ||
112 | else | ||
113 | ramdac580 &= head_a ? 0xfffffeff : 0xefffffff; | ||
114 | |||
115 | return ramdac580; | ||
116 | } | ||
117 | |||
118 | static void | ||
119 | setPLL_double_highregs(struct nv04_clock_priv *priv, u32 reg1, | ||
120 | struct nouveau_pll_vals *pv) | ||
121 | { | ||
122 | int chip_version = nouveau_bios(priv)->version.chip; | ||
123 | bool nv3035 = chip_version == 0x30 || chip_version == 0x35; | ||
124 | uint32_t reg2 = reg1 + ((reg1 == 0x680520) ? 0x5c : 0x70); | ||
125 | uint32_t oldpll1 = nv_rd32(priv, reg1); | ||
126 | uint32_t oldpll2 = !nv3035 ? nv_rd32(priv, reg2) : 0; | ||
127 | uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; | ||
128 | uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; | ||
129 | uint32_t oldramdac580 = 0, ramdac580 = 0; | ||
130 | bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */ | ||
131 | uint32_t saved_powerctrl_1 = 0, savedc040 = 0; | ||
132 | int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1); | ||
133 | |||
134 | /* model specific additions to generic pll1 and pll2 set up above */ | ||
135 | if (nv3035) { | ||
136 | pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 | | ||
137 | (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4; | ||
138 | pll2 = 0; | ||
139 | } | ||
140 | if (chip_version > 0x40 && reg1 >= 0x680508) { /* !nv40 */ | ||
141 | oldramdac580 = nv_rd32(priv, 0x680580); | ||
142 | ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); | ||
143 | if (oldramdac580 != ramdac580) | ||
144 | oldpll1 = ~0; /* force mismatch */ | ||
145 | if (single_stage) | ||
146 | /* magic value used by nvidia in single stage mode */ | ||
147 | pll2 |= 0x011f; | ||
148 | } | ||
149 | if (chip_version > 0x70) | ||
150 | /* magic bits set by the blob (but not the bios) on g71-73 */ | ||
151 | pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28; | ||
152 | |||
153 | if (oldpll1 == pll1 && oldpll2 == pll2) | ||
154 | return; /* already set */ | ||
155 | |||
156 | if (shift_powerctrl_1 >= 0) { | ||
157 | saved_powerctrl_1 = nv_rd32(priv, 0x001584); | ||
158 | nv_wr32(priv, 0x001584, | ||
159 | (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | | ||
160 | 1 << shift_powerctrl_1); | ||
161 | } | ||
162 | |||
163 | if (chip_version >= 0x40) { | ||
164 | int shift_c040 = 14; | ||
165 | |||
166 | switch (reg1) { | ||
167 | case 0x680504: | ||
168 | shift_c040 += 2; | ||
169 | case 0x680500: | ||
170 | shift_c040 += 2; | ||
171 | case 0x680520: | ||
172 | shift_c040 += 2; | ||
173 | case 0x680508: | ||
174 | shift_c040 += 2; | ||
175 | } | ||
176 | |||
177 | savedc040 = nv_rd32(priv, 0xc040); | ||
178 | if (shift_c040 != 14) | ||
179 | nv_wr32(priv, 0xc040, savedc040 & ~(3 << shift_c040)); | ||
180 | } | ||
181 | |||
182 | if (oldramdac580 != ramdac580) | ||
183 | nv_wr32(priv, 0x680580, ramdac580); | ||
184 | |||
185 | if (!nv3035) | ||
186 | nv_wr32(priv, reg2, pll2); | ||
187 | nv_wr32(priv, reg1, pll1); | ||
188 | |||
189 | if (shift_powerctrl_1 >= 0) | ||
190 | nv_wr32(priv, 0x001584, saved_powerctrl_1); | ||
191 | if (chip_version >= 0x40) | ||
192 | nv_wr32(priv, 0xc040, savedc040); | ||
193 | } | ||
194 | |||
195 | static void | ||
196 | setPLL_double_lowregs(struct nv04_clock_priv *priv, u32 NMNMreg, | ||
197 | struct nouveau_pll_vals *pv) | ||
198 | { | ||
199 | /* When setting PLLs, there is a merry game of disabling and enabling | ||
200 | * various bits of hardware during the process. This function is a | ||
201 | * synthesis of six nv4x traces, nearly each card doing a subtly | ||
202 | * different thing. With luck all the necessary bits for each card are | ||
203 | * combined herein. Without luck it deviates from each card's formula | ||
204 | * so as to not work on any :) | ||
205 | */ | ||
206 | |||
207 | uint32_t Preg = NMNMreg - 4; | ||
208 | bool mpll = Preg == 0x4020; | ||
209 | uint32_t oldPval = nv_rd32(priv, Preg); | ||
210 | uint32_t NMNM = pv->NM2 << 16 | pv->NM1; | ||
211 | uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | | ||
212 | 0xc << 28 | pv->log2P << 16; | ||
213 | uint32_t saved4600 = 0; | ||
214 | /* some cards have different maskc040s */ | ||
215 | uint32_t maskc040 = ~(3 << 14), savedc040; | ||
216 | bool single_stage = !pv->NM2 || pv->N2 == pv->M2; | ||
217 | |||
218 | if (nv_rd32(priv, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) | ||
219 | return; | ||
220 | |||
221 | if (Preg == 0x4000) | ||
222 | maskc040 = ~0x333; | ||
223 | if (Preg == 0x4058) | ||
224 | maskc040 = ~(0xc << 24); | ||
225 | |||
226 | if (mpll) { | ||
227 | struct nvbios_pll info; | ||
228 | uint8_t Pval2; | ||
229 | |||
230 | if (nvbios_pll_parse(nouveau_bios(priv), Preg, &info)) | ||
231 | return; | ||
232 | |||
233 | Pval2 = pv->log2P + info.bias_p; | ||
234 | if (Pval2 > info.max_p) | ||
235 | Pval2 = info.max_p; | ||
236 | Pval |= 1 << 28 | Pval2 << 20; | ||
237 | |||
238 | saved4600 = nv_rd32(priv, 0x4600); | ||
239 | nv_wr32(priv, 0x4600, saved4600 | 8 << 28); | ||
240 | } | ||
241 | if (single_stage) | ||
242 | Pval |= mpll ? 1 << 12 : 1 << 8; | ||
243 | |||
244 | nv_wr32(priv, Preg, oldPval | 1 << 28); | ||
245 | nv_wr32(priv, Preg, Pval & ~(4 << 28)); | ||
246 | if (mpll) { | ||
247 | Pval |= 8 << 20; | ||
248 | nv_wr32(priv, 0x4020, Pval & ~(0xc << 28)); | ||
249 | nv_wr32(priv, 0x4038, Pval & ~(0xc << 28)); | ||
250 | } | ||
251 | |||
252 | savedc040 = nv_rd32(priv, 0xc040); | ||
253 | nv_wr32(priv, 0xc040, savedc040 & maskc040); | ||
254 | |||
255 | nv_wr32(priv, NMNMreg, NMNM); | ||
256 | if (NMNMreg == 0x4024) | ||
257 | nv_wr32(priv, 0x403c, NMNM); | ||
258 | |||
259 | nv_wr32(priv, Preg, Pval); | ||
260 | if (mpll) { | ||
261 | Pval &= ~(8 << 20); | ||
262 | nv_wr32(priv, 0x4020, Pval); | ||
263 | nv_wr32(priv, 0x4038, Pval); | ||
264 | nv_wr32(priv, 0x4600, saved4600); | ||
265 | } | ||
266 | |||
267 | nv_wr32(priv, 0xc040, savedc040); | ||
268 | |||
269 | if (mpll) { | ||
270 | nv_wr32(priv, 0x4020, Pval & ~(1 << 28)); | ||
271 | nv_wr32(priv, 0x4038, Pval & ~(1 << 28)); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | int | ||
32 | nv04_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | 276 | nv04_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) |
33 | { | 277 | { |
34 | struct nv04_clock_priv *priv = (void *)clk; | 278 | struct nv04_clock_priv *priv = (void *)clk; |
279 | struct nouveau_pll_vals pv; | ||
280 | struct nvbios_pll info; | ||
281 | int ret; | ||
282 | |||
283 | ret = nvbios_pll_parse(nouveau_bios(priv), type > 0x405c ? | ||
284 | type : type - 4, &info); | ||
285 | if (ret) | ||
286 | return ret; | ||
287 | |||
288 | ret = clk->pll_calc(clk, &info, freq, &pv); | ||
289 | if (!ret) | ||
290 | return ret; | ||
291 | |||
292 | return clk->pll_prog(clk, type, &pv); | ||
293 | } | ||
35 | 294 | ||
36 | nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); | 295 | int |
296 | nv04_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, | ||
297 | int clk, struct nouveau_pll_vals *pv) | ||
298 | { | ||
299 | int N1, M1, N2, M2, P; | ||
300 | int ret = nv04_pll_calc(clock, info, clk, &N1, &M1, &N2, &M2, &P); | ||
301 | if (ret) { | ||
302 | pv->refclk = info->refclk; | ||
303 | pv->N1 = N1; | ||
304 | pv->M1 = M1; | ||
305 | pv->N2 = N2; | ||
306 | pv->M2 = M2; | ||
307 | pv->log2P = P; | ||
308 | } | ||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | int | ||
313 | nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1, | ||
314 | struct nouveau_pll_vals *pv) | ||
315 | { | ||
316 | struct nv04_clock_priv *priv = (void *)clk; | ||
317 | int cv = nouveau_bios(clk)->version.chip; | ||
318 | |||
319 | if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || | ||
320 | cv >= 0x40) { | ||
321 | if (reg1 > 0x405c) | ||
322 | setPLL_double_highregs(priv, reg1, pv); | ||
323 | else | ||
324 | setPLL_double_lowregs(priv, reg1, pv); | ||
325 | } else | ||
326 | setPLL_single(priv, reg1, pv); | ||
327 | |||
328 | return 0; | ||
37 | } | 329 | } |
38 | 330 | ||
39 | static int | 331 | static int |
@@ -50,6 +342,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
50 | return ret; | 342 | return ret; |
51 | 343 | ||
52 | priv->base.pll_set = nv04_clock_pll_set; | 344 | priv->base.pll_set = nv04_clock_pll_set; |
345 | priv->base.pll_calc = nv04_clock_pll_calc; | ||
346 | priv->base.pll_prog = nv04_clock_pll_prog; | ||
53 | return 0; | 347 | return 0; |
54 | } | 348 | } |
55 | 349 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c index 60d1ca44e39c..a4b2b7ebf9af 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c | |||
@@ -28,14 +28,6 @@ struct nv40_clock_priv { | |||
28 | struct nouveau_clock base; | 28 | struct nouveau_clock base; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static void | ||
32 | nv40_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | ||
33 | { | ||
34 | struct nv40_clock_priv *priv = (void *)clk; | ||
35 | |||
36 | nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); | ||
37 | } | ||
38 | |||
39 | static int | 31 | static int |
40 | nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 32 | nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
41 | struct nouveau_oclass *oclass, void *data, u32 size, | 33 | struct nouveau_oclass *oclass, void *data, u32 size, |
@@ -49,7 +41,9 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
49 | if (ret) | 41 | if (ret) |
50 | return ret; | 42 | return ret; |
51 | 43 | ||
52 | priv->base.pll_set = nv40_clock_pll_set; | 44 | priv->base.pll_set = nv04_clock_pll_set; |
45 | priv->base.pll_calc = nv04_clock_pll_calc; | ||
46 | priv->base.pll_prog = nv04_clock_pll_prog; | ||
53 | return 0; | 47 | return 0; |
54 | } | 48 | } |
55 | 49 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c index 82804bdcec31..fd181fbceddb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c | |||
@@ -23,17 +23,57 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/clock.h> | 25 | #include <subdev/clock.h> |
26 | #include <subdev/bios.h> | ||
27 | #include <subdev/bios/pll.h> | ||
28 | |||
29 | #include "pll.h" | ||
26 | 30 | ||
27 | struct nv50_clock_priv { | 31 | struct nv50_clock_priv { |
28 | struct nouveau_clock base; | 32 | struct nouveau_clock base; |
29 | }; | 33 | }; |
30 | 34 | ||
31 | static void | 35 | static int |
32 | nv50_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | 36 | nv50_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) |
33 | { | 37 | { |
34 | struct nv50_clock_priv *priv = (void *)clk; | 38 | struct nv50_clock_priv *priv = (void *)clk; |
39 | struct nouveau_bios *bios = nouveau_bios(priv); | ||
40 | struct nvbios_pll info; | ||
41 | int N1, M1, N2, M2, P; | ||
42 | int ret; | ||
43 | |||
44 | ret = nvbios_pll_parse(bios, type, &info); | ||
45 | if (ret) { | ||
46 | nv_error(clk, "failed to retrieve pll data, %d\n", ret); | ||
47 | return ret; | ||
48 | } | ||
35 | 49 | ||
36 | nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); | 50 | ret = nv04_pll_calc(clk, &info, freq, &N1, &M1, &N2, &M2, &P); |
51 | if (!ret) { | ||
52 | nv_error(clk, "failed pll calculation\n"); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | switch (info.type) { | ||
57 | case PLL_VPLL0: | ||
58 | case PLL_VPLL1: | ||
59 | nv_wr32(priv, info.reg + 0, 0x10000611); | ||
60 | nv_mask(priv, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1); | ||
61 | nv_mask(priv, info.reg + 8, 0x7fff00ff, (P << 28) | | ||
62 | (M2 << 16) | N2); | ||
63 | break; | ||
64 | case PLL_MEMORY: | ||
65 | nv_mask(priv, info.reg + 0, 0x01ff0000, (P << 22) | | ||
66 | (info.bias_p << 19) | | ||
67 | (P << 16)); | ||
68 | nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); | ||
69 | break; | ||
70 | default: | ||
71 | nv_mask(priv, info.reg + 0, 0x00070000, (P << 16)); | ||
72 | nv_wr32(priv, info.reg + 4, (N1 << 8) | M1); | ||
73 | break; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
37 | } | 77 | } |
38 | 78 | ||
39 | static int | 79 | static int |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index 876ec46e2b41..cc8d7d162d7c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c | |||
@@ -23,17 +23,47 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/clock.h> | 25 | #include <subdev/clock.h> |
26 | #include <subdev/bios.h> | ||
27 | #include <subdev/bios/pll.h> | ||
28 | |||
29 | #include "pll.h" | ||
26 | 30 | ||
27 | struct nva3_clock_priv { | 31 | struct nva3_clock_priv { |
28 | struct nouveau_clock base; | 32 | struct nouveau_clock base; |
29 | }; | 33 | }; |
30 | 34 | ||
31 | static void | 35 | static int |
32 | nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | 36 | nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) |
33 | { | 37 | { |
34 | struct nva3_clock_priv *priv = (void *)clk; | 38 | struct nva3_clock_priv *priv = (void *)clk; |
39 | struct nouveau_bios *bios = nouveau_bios(priv); | ||
40 | struct nvbios_pll info; | ||
41 | int N, fN, M, P; | ||
42 | int ret; | ||
43 | |||
44 | ret = nvbios_pll_parse(bios, type, &info); | ||
45 | if (ret) | ||
46 | return ret; | ||
47 | |||
48 | ret = nva3_pll_calc(clk, &info, freq, &N, &fN, &M, &P); | ||
49 | if (ret < 0) | ||
50 | return ret; | ||
51 | |||
52 | switch (info.type) { | ||
53 | case PLL_VPLL0: | ||
54 | case PLL_VPLL1: | ||
55 | nv_wr32(priv, info.reg + 0, 0x50000610); | ||
56 | nv_mask(priv, info.reg + 4, 0x003fffff, | ||
57 | (P << 16) | (M << 8) | N); | ||
58 | nv_wr32(priv, info.reg + 8, fN); | ||
59 | break; | ||
60 | default: | ||
61 | nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); | ||
62 | ret = -EINVAL; | ||
63 | break; | ||
64 | } | ||
35 | 65 | ||
36 | nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); | 66 | return ret; |
37 | } | 67 | } |
38 | 68 | ||
39 | static int | 69 | static int |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 00641566f2e7..5ccce0b17bf3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | |||
@@ -23,17 +23,46 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/clock.h> | 25 | #include <subdev/clock.h> |
26 | #include <subdev/bios.h> | ||
27 | #include <subdev/bios/pll.h> | ||
28 | |||
29 | #include "pll.h" | ||
26 | 30 | ||
27 | struct nvc0_clock_priv { | 31 | struct nvc0_clock_priv { |
28 | struct nouveau_clock base; | 32 | struct nouveau_clock base; |
29 | }; | 33 | }; |
30 | 34 | ||
31 | static void | 35 | static int |
32 | nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | 36 | nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) |
33 | { | 37 | { |
34 | struct nvc0_clock_priv *priv = (void *)clk; | 38 | struct nvc0_clock_priv *priv = (void *)clk; |
39 | struct nouveau_bios *bios = nouveau_bios(priv); | ||
40 | struct nvbios_pll info; | ||
41 | int N, fN, M, P; | ||
42 | int ret; | ||
43 | |||
44 | ret = nvbios_pll_parse(bios, type, &info); | ||
45 | if (ret) | ||
46 | return ret; | ||
47 | |||
48 | ret = nva3_pll_calc(clk, &info, freq, &N, &fN, &M, &P); | ||
49 | if (ret < 0) | ||
50 | return ret; | ||
51 | |||
52 | switch (info.type) { | ||
53 | case PLL_VPLL0: | ||
54 | case PLL_VPLL1: | ||
55 | nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); | ||
56 | nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); | ||
57 | nv_wr32(priv, info.reg + 0x10, fN << 16); | ||
58 | break; | ||
59 | default: | ||
60 | nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); | ||
61 | ret = -EINVAL; | ||
62 | break; | ||
63 | } | ||
35 | 64 | ||
36 | nv_warn(priv, "0x%08x/%dKhz unimplemented\n", type, freq); | 65 | return ret; |
37 | } | 66 | } |
38 | 67 | ||
39 | static int | 68 | static int |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h b/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h new file mode 100644 index 000000000000..ef2c0078f337 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pll.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef __NOUVEAU_PLL_H__ | ||
2 | #define __NOUVEAU_PLL_H__ | ||
3 | |||
4 | int nv04_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, | ||
5 | int *N1, int *M1, int *N2, int *M2, int *P); | ||
6 | int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, | ||
7 | int *N, int *fN, int *M, int *P); | ||
8 | |||
9 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c new file mode 100644 index 000000000000..a2ab6d051ba8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * Copyright 1993-2003 NVIDIA, Corporation | ||
3 | * Copyright 2007-2009 Stuart Bennett | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice shall be included in | ||
13 | * all copies or substantial portions of the Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | ||
20 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | * SOFTWARE. | ||
22 | */ | ||
23 | |||
24 | #include <subdev/clock.h> | ||
25 | #include <subdev/bios.h> | ||
26 | #include <subdev/bios/pll.h> | ||
27 | |||
28 | #include "pll.h" | ||
29 | |||
30 | static int | ||
31 | getMNP_single(struct nouveau_clock *clock, struct nvbios_pll *info, int clk, | ||
32 | int *pN, int *pM, int *pP) | ||
33 | { | ||
34 | /* Find M, N and P for a single stage PLL | ||
35 | * | ||
36 | * Note that some bioses (NV3x) have lookup tables of precomputed MNP | ||
37 | * values, but we're too lazy to use those atm | ||
38 | * | ||
39 | * "clk" parameter in kHz | ||
40 | * returns calculated clock | ||
41 | */ | ||
42 | int cv = nouveau_bios(clock)->version.chip; | ||
43 | int minvco = info->vco1.min_freq, maxvco = info->vco1.max_freq; | ||
44 | int minM = info->vco1.min_m, maxM = info->vco1.max_m; | ||
45 | int minN = info->vco1.min_n, maxN = info->vco1.max_n; | ||
46 | int minU = info->vco1.min_inputfreq; | ||
47 | int maxU = info->vco1.max_inputfreq; | ||
48 | int minP = info->min_p; | ||
49 | int maxP = info->max_p_usable; | ||
50 | int crystal = info->refclk; | ||
51 | int M, N, thisP, P; | ||
52 | int clkP, calcclk; | ||
53 | int delta, bestdelta = INT_MAX; | ||
54 | int bestclk = 0; | ||
55 | |||
56 | /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */ | ||
57 | /* possibly correlated with introduction of 27MHz crystal */ | ||
58 | if (cv < 0x17 || cv == 0x1a || cv == 0x20) { | ||
59 | if (clk > 250000) | ||
60 | maxM = 6; | ||
61 | if (clk > 340000) | ||
62 | maxM = 2; | ||
63 | } else if (cv < 0x40) { | ||
64 | if (clk > 150000) | ||
65 | maxM = 6; | ||
66 | if (clk > 200000) | ||
67 | maxM = 4; | ||
68 | if (clk > 340000) | ||
69 | maxM = 2; | ||
70 | } | ||
71 | |||
72 | P = 1 << maxP; | ||
73 | if ((clk * P) < minvco) { | ||
74 | minvco = clk * maxP; | ||
75 | maxvco = minvco * 2; | ||
76 | } | ||
77 | |||
78 | if (clk + clk/200 > maxvco) /* +0.5% */ | ||
79 | maxvco = clk + clk/200; | ||
80 | |||
81 | /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */ | ||
82 | for (thisP = minP; thisP <= maxP; thisP++) { | ||
83 | P = 1 << thisP; | ||
84 | clkP = clk * P; | ||
85 | |||
86 | if (clkP < minvco) | ||
87 | continue; | ||
88 | if (clkP > maxvco) | ||
89 | return bestclk; | ||
90 | |||
91 | for (M = minM; M <= maxM; M++) { | ||
92 | if (crystal/M < minU) | ||
93 | return bestclk; | ||
94 | if (crystal/M > maxU) | ||
95 | continue; | ||
96 | |||
97 | /* add crystal/2 to round better */ | ||
98 | N = (clkP * M + crystal/2) / crystal; | ||
99 | |||
100 | if (N < minN) | ||
101 | continue; | ||
102 | if (N > maxN) | ||
103 | break; | ||
104 | |||
105 | /* more rounding additions */ | ||
106 | calcclk = ((N * crystal + P/2) / P + M/2) / M; | ||
107 | delta = abs(calcclk - clk); | ||
108 | /* we do an exhaustive search rather than terminating | ||
109 | * on an optimality condition... | ||
110 | */ | ||
111 | if (delta < bestdelta) { | ||
112 | bestdelta = delta; | ||
113 | bestclk = calcclk; | ||
114 | *pN = N; | ||
115 | *pM = M; | ||
116 | *pP = thisP; | ||
117 | if (delta == 0) /* except this one */ | ||
118 | return bestclk; | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | |||
123 | return bestclk; | ||
124 | } | ||
125 | |||
126 | static int | ||
127 | getMNP_double(struct nouveau_clock *clock, struct nvbios_pll *info, int clk, | ||
128 | int *pN1, int *pM1, int *pN2, int *pM2, int *pP) | ||
129 | { | ||
130 | /* Find M, N and P for a two stage PLL | ||
131 | * | ||
132 | * Note that some bioses (NV30+) have lookup tables of precomputed MNP | ||
133 | * values, but we're too lazy to use those atm | ||
134 | * | ||
135 | * "clk" parameter in kHz | ||
136 | * returns calculated clock | ||
137 | */ | ||
138 | int chip_version = nouveau_bios(clock)->version.chip; | ||
139 | int minvco1 = info->vco1.min_freq, maxvco1 = info->vco1.max_freq; | ||
140 | int minvco2 = info->vco2.min_freq, maxvco2 = info->vco2.max_freq; | ||
141 | int minU1 = info->vco1.min_inputfreq, minU2 = info->vco2.min_inputfreq; | ||
142 | int maxU1 = info->vco1.max_inputfreq, maxU2 = info->vco2.max_inputfreq; | ||
143 | int minM1 = info->vco1.min_m, maxM1 = info->vco1.max_m; | ||
144 | int minN1 = info->vco1.min_n, maxN1 = info->vco1.max_n; | ||
145 | int minM2 = info->vco2.min_m, maxM2 = info->vco2.max_m; | ||
146 | int minN2 = info->vco2.min_n, maxN2 = info->vco2.max_n; | ||
147 | int maxlog2P = info->max_p_usable; | ||
148 | int crystal = info->refclk; | ||
149 | bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2); | ||
150 | int M1, N1, M2, N2, log2P; | ||
151 | int clkP, calcclk1, calcclk2, calcclkout; | ||
152 | int delta, bestdelta = INT_MAX; | ||
153 | int bestclk = 0; | ||
154 | |||
155 | int vco2 = (maxvco2 - maxvco2/200) / 2; | ||
156 | for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++) | ||
157 | ; | ||
158 | clkP = clk << log2P; | ||
159 | |||
160 | if (maxvco2 < clk + clk/200) /* +0.5% */ | ||
161 | maxvco2 = clk + clk/200; | ||
162 | |||
163 | for (M1 = minM1; M1 <= maxM1; M1++) { | ||
164 | if (crystal/M1 < minU1) | ||
165 | return bestclk; | ||
166 | if (crystal/M1 > maxU1) | ||
167 | continue; | ||
168 | |||
169 | for (N1 = minN1; N1 <= maxN1; N1++) { | ||
170 | calcclk1 = crystal * N1 / M1; | ||
171 | if (calcclk1 < minvco1) | ||
172 | continue; | ||
173 | if (calcclk1 > maxvco1) | ||
174 | break; | ||
175 | |||
176 | for (M2 = minM2; M2 <= maxM2; M2++) { | ||
177 | if (calcclk1/M2 < minU2) | ||
178 | break; | ||
179 | if (calcclk1/M2 > maxU2) | ||
180 | continue; | ||
181 | |||
182 | /* add calcclk1/2 to round better */ | ||
183 | N2 = (clkP * M2 + calcclk1/2) / calcclk1; | ||
184 | if (N2 < minN2) | ||
185 | continue; | ||
186 | if (N2 > maxN2) | ||
187 | break; | ||
188 | |||
189 | if (!fixedgain2) { | ||
190 | if (chip_version < 0x60) | ||
191 | if (N2/M2 < 4 || N2/M2 > 10) | ||
192 | continue; | ||
193 | |||
194 | calcclk2 = calcclk1 * N2 / M2; | ||
195 | if (calcclk2 < minvco2) | ||
196 | break; | ||
197 | if (calcclk2 > maxvco2) | ||
198 | continue; | ||
199 | } else | ||
200 | calcclk2 = calcclk1; | ||
201 | |||
202 | calcclkout = calcclk2 >> log2P; | ||
203 | delta = abs(calcclkout - clk); | ||
204 | /* we do an exhaustive search rather than terminating | ||
205 | * on an optimality condition... | ||
206 | */ | ||
207 | if (delta < bestdelta) { | ||
208 | bestdelta = delta; | ||
209 | bestclk = calcclkout; | ||
210 | *pN1 = N1; | ||
211 | *pM1 = M1; | ||
212 | *pN2 = N2; | ||
213 | *pM2 = M2; | ||
214 | *pP = log2P; | ||
215 | if (delta == 0) /* except this one */ | ||
216 | return bestclk; | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | return bestclk; | ||
223 | } | ||
224 | |||
225 | int | ||
226 | nv04_pll_calc(struct nouveau_clock *clk, struct nvbios_pll *info, u32 freq, | ||
227 | int *N1, int *M1, int *N2, int *M2, int *P) | ||
228 | { | ||
229 | int ret; | ||
230 | |||
231 | if (!info->vco2.max_freq) { | ||
232 | ret = getMNP_single(clk, info, freq, N1, M1, P); | ||
233 | *N2 = 1; | ||
234 | *M2 = 1; | ||
235 | } else { | ||
236 | ret = getMNP_double(clk, info, freq, N1, M1, N2, M2, P); | ||
237 | } | ||
238 | |||
239 | if (!ret) | ||
240 | nv_error(clk, "unable to compute acceptable pll values\n"); | ||
241 | return ret; | ||
242 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c index 8cf63a8b30cd..eed5c16cf610 100644 --- a/drivers/gpu/drm/nouveau/nv50_calc.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c | |||
@@ -22,60 +22,43 @@ | |||
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "drmP.h" | 25 | #include <subdev/clock.h> |
26 | #include "nouveau_drv.h" | 26 | #include <subdev/bios.h> |
27 | #include "nouveau_hw.h" | 27 | #include <subdev/bios/pll.h> |
28 | 28 | ||
29 | int | 29 | #include "pll.h" |
30 | nv50_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, | ||
31 | int *N1, int *M1, int *N2, int *M2, int *P) | ||
32 | { | ||
33 | struct nouveau_pll_vals pll_vals; | ||
34 | int ret; | ||
35 | |||
36 | ret = nouveau_calc_pll_mnp(dev, pll, clk, &pll_vals); | ||
37 | if (ret <= 0) | ||
38 | return ret; | ||
39 | |||
40 | *N1 = pll_vals.N1; | ||
41 | *M1 = pll_vals.M1; | ||
42 | *N2 = pll_vals.N2; | ||
43 | *M2 = pll_vals.M2; | ||
44 | *P = pll_vals.log2P; | ||
45 | return ret; | ||
46 | } | ||
47 | 30 | ||
48 | int | 31 | int |
49 | nva3_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, | 32 | nva3_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, |
50 | int *pN, int *pfN, int *pM, int *P) | 33 | u32 freq, int *pN, int *pfN, int *pM, int *P) |
51 | { | 34 | { |
52 | u32 best_err = ~0, err; | 35 | u32 best_err = ~0, err; |
53 | int M, lM, hM, N, fN; | 36 | int M, lM, hM, N, fN; |
54 | 37 | ||
55 | *P = pll->vco1.maxfreq / clk; | 38 | *P = info->vco1.max_freq / freq; |
56 | if (*P > pll->max_p) | 39 | if (*P > info->max_p) |
57 | *P = pll->max_p; | 40 | *P = info->max_p; |
58 | if (*P < pll->min_p) | 41 | if (*P < info->min_p) |
59 | *P = pll->min_p; | 42 | *P = info->min_p; |
60 | 43 | ||
61 | lM = (pll->refclk + pll->vco1.max_inputfreq) / pll->vco1.max_inputfreq; | 44 | lM = (info->refclk + info->vco1.max_inputfreq) / info->vco1.max_inputfreq; |
62 | lM = max(lM, (int)pll->vco1.min_m); | 45 | lM = max(lM, (int)info->vco1.min_m); |
63 | hM = (pll->refclk + pll->vco1.min_inputfreq) / pll->vco1.min_inputfreq; | 46 | hM = (info->refclk + info->vco1.min_inputfreq) / info->vco1.min_inputfreq; |
64 | hM = min(hM, (int)pll->vco1.max_m); | 47 | hM = min(hM, (int)info->vco1.max_m); |
65 | 48 | ||
66 | for (M = lM; M <= hM; M++) { | 49 | for (M = lM; M <= hM; M++) { |
67 | u32 tmp = clk * *P * M; | 50 | u32 tmp = freq * *P * M; |
68 | N = tmp / pll->refclk; | 51 | N = tmp / info->refclk; |
69 | fN = tmp % pll->refclk; | 52 | fN = tmp % info->refclk; |
70 | if (!pfN && fN >= pll->refclk / 2) | 53 | if (!pfN && fN >= info->refclk / 2) |
71 | N++; | 54 | N++; |
72 | 55 | ||
73 | if (N < pll->vco1.min_n) | 56 | if (N < info->vco1.min_n) |
74 | continue; | 57 | continue; |
75 | if (N > pll->vco1.max_n) | 58 | if (N > info->vco1.max_n) |
76 | break; | 59 | break; |
77 | 60 | ||
78 | err = abs(clk - (pll->refclk * N / M / *P)); | 61 | err = abs(freq - (info->refclk * N / M / *P)); |
79 | if (err < best_err) { | 62 | if (err < best_err) { |
80 | best_err = err; | 63 | best_err = err; |
81 | *pN = N; | 64 | *pN = N; |
@@ -83,15 +66,15 @@ nva3_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, | |||
83 | } | 66 | } |
84 | 67 | ||
85 | if (pfN) { | 68 | if (pfN) { |
86 | *pfN = (((fN << 13) / pll->refclk) - 4096) & 0xffff; | 69 | *pfN = (((fN << 13) / info->refclk) - 4096) & 0xffff; |
87 | return clk; | 70 | return freq; |
88 | } | 71 | } |
89 | } | 72 | } |
90 | 73 | ||
91 | if (unlikely(best_err == ~0)) { | 74 | if (unlikely(best_err == ~0)) { |
92 | NV_ERROR(dev, "unable to find matching pll values\n"); | 75 | nv_error(clock, "unable to find matching pll values\n"); |
93 | return -EINVAL; | 76 | return -EINVAL; |
94 | } | 77 | } |
95 | 78 | ||
96 | return pll->refclk * *pN / *pM / *P; | 79 | return info->refclk * *pN / *pM / *P; |
97 | } | 80 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 35b0a8f9c008..98eaac9da30e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -441,70 +441,6 @@ io_condition_met(struct nvbios *bios, uint16_t offset, uint8_t cond) | |||
441 | return (data == cmpval); | 441 | return (data == cmpval); |
442 | } | 442 | } |
443 | 443 | ||
444 | static int | ||
445 | nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk) | ||
446 | { | ||
447 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
448 | struct nouveau_pll_vals pll; | ||
449 | struct pll_lims pll_limits; | ||
450 | u32 ctrl, mask, coef; | ||
451 | int ret; | ||
452 | |||
453 | ret = get_pll_limits(dev, reg, &pll_limits); | ||
454 | if (ret) | ||
455 | return ret; | ||
456 | |||
457 | clk = nouveau_calc_pll_mnp(dev, &pll_limits, clk, &pll); | ||
458 | if (!clk) | ||
459 | return -ERANGE; | ||
460 | |||
461 | coef = pll.N1 << 8 | pll.M1; | ||
462 | ctrl = pll.log2P << 16; | ||
463 | mask = 0x00070000; | ||
464 | if (reg == 0x004008) { | ||
465 | mask |= 0x01f80000; | ||
466 | ctrl |= (pll_limits.log2p_bias << 19); | ||
467 | ctrl |= (pll.log2P << 22); | ||
468 | } | ||
469 | |||
470 | if (!dev_priv->vbios.execute) | ||
471 | return 0; | ||
472 | |||
473 | nv_mask(dev, reg + 0, mask, ctrl); | ||
474 | nv_wr32(dev, reg + 4, coef); | ||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static int | ||
479 | setPLL(struct nvbios *bios, uint32_t reg, uint32_t clk) | ||
480 | { | ||
481 | struct drm_device *dev = bios->dev; | ||
482 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
483 | /* clk in kHz */ | ||
484 | struct pll_lims pll_lim; | ||
485 | struct nouveau_pll_vals pllvals; | ||
486 | int ret; | ||
487 | |||
488 | if (dev_priv->card_type >= NV_50) | ||
489 | return nv50_pll_set(dev, reg, clk); | ||
490 | |||
491 | /* high regs (such as in the mac g5 table) are not -= 4 */ | ||
492 | ret = get_pll_limits(dev, reg > 0x405c ? reg : reg - 4, &pll_lim); | ||
493 | if (ret) | ||
494 | return ret; | ||
495 | |||
496 | clk = nouveau_calc_pll_mnp(dev, &pll_lim, clk, &pllvals); | ||
497 | if (!clk) | ||
498 | return -ERANGE; | ||
499 | |||
500 | if (bios->execute) { | ||
501 | still_alive(); | ||
502 | nouveau_hw_setpll(dev, reg, &pllvals); | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int dcb_entry_idx_from_crtchead(struct drm_device *dev) | 444 | static int dcb_entry_idx_from_crtchead(struct drm_device *dev) |
509 | { | 445 | { |
510 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 446 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
@@ -752,7 +688,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, | |||
752 | BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n", | 688 | BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n", |
753 | offset, reg, config, freq); | 689 | offset, reg, config, freq); |
754 | 690 | ||
755 | setPLL(bios, reg, freq * 10); | 691 | setPLL(bios->dev, reg, freq * 10); |
756 | 692 | ||
757 | return len; | 693 | return len; |
758 | } | 694 | } |
@@ -1110,7 +1046,7 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, | |||
1110 | BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n", | 1046 | BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n", |
1111 | offset, reg, config, freq); | 1047 | offset, reg, config, freq); |
1112 | 1048 | ||
1113 | setPLL(bios, reg, freq); | 1049 | setPLL(bios->dev, reg, freq); |
1114 | 1050 | ||
1115 | return len; | 1051 | return len; |
1116 | } | 1052 | } |
@@ -1137,7 +1073,7 @@ init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1137 | BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n", | 1073 | BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n", |
1138 | offset, reg, freq); | 1074 | offset, reg, freq); |
1139 | 1075 | ||
1140 | setPLL(bios, reg, freq); | 1076 | setPLL(bios->dev, reg, freq); |
1141 | return 9; | 1077 | return 9; |
1142 | } | 1078 | } |
1143 | 1079 | ||
@@ -2376,12 +2312,12 @@ init_configure_clk(struct nvbios *bios, uint16_t offset, | |||
2376 | return 0; | 2312 | return 0; |
2377 | 2313 | ||
2378 | clock = ROM16(bios->data[meminitoffs + 4]) * 10; | 2314 | clock = ROM16(bios->data[meminitoffs + 4]) * 10; |
2379 | setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock); | 2315 | setPLL(bios->dev, NV_PRAMDAC_NVPLL_COEFF, clock); |
2380 | 2316 | ||
2381 | clock = ROM16(bios->data[meminitoffs + 2]) * 10; | 2317 | clock = ROM16(bios->data[meminitoffs + 2]) * 10; |
2382 | if (bios->data[meminitoffs] & 1) /* DDR */ | 2318 | if (bios->data[meminitoffs] & 1) /* DDR */ |
2383 | clock *= 2; | 2319 | clock *= 2; |
2384 | setPLL(bios, NV_PRAMDAC_MPLL_COEFF, clock); | 2320 | setPLL(bios->dev, NV_PRAMDAC_MPLL_COEFF, clock); |
2385 | 2321 | ||
2386 | return 1; | 2322 | return 1; |
2387 | } | 2323 | } |
@@ -2820,7 +2756,7 @@ init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
2820 | 2756 | ||
2821 | BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq); | 2757 | BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq); |
2822 | 2758 | ||
2823 | setPLL(bios, reg, freq * 10); | 2759 | setPLL(bios->dev, reg, freq * 10); |
2824 | 2760 | ||
2825 | return 7; | 2761 | return 7; |
2826 | } | 2762 | } |
@@ -2898,7 +2834,7 @@ init_ram_restrict_pll(struct nvbios *bios, uint16_t offset, | |||
2898 | "Type %02x Reg 0x%08x Freq %dKHz\n", | 2834 | "Type %02x Reg 0x%08x Freq %dKHz\n", |
2899 | offset, type, reg, freq); | 2835 | offset, type, reg, freq); |
2900 | 2836 | ||
2901 | setPLL(bios, reg, freq); | 2837 | setPLL(bios->dev, reg, freq); |
2902 | return len; | 2838 | return len; |
2903 | } | 2839 | } |
2904 | } | 2840 | } |
@@ -4305,447 +4241,6 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i | |||
4305 | return 0; | 4241 | return 0; |
4306 | } | 4242 | } |
4307 | 4243 | ||
4308 | struct pll_mapping { | ||
4309 | u8 type; | ||
4310 | u32 reg; | ||
4311 | }; | ||
4312 | |||
4313 | static struct pll_mapping nv04_pll_mapping[] = { | ||
4314 | { PLL_CORE , NV_PRAMDAC_NVPLL_COEFF }, | ||
4315 | { PLL_MEMORY, NV_PRAMDAC_MPLL_COEFF }, | ||
4316 | { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, | ||
4317 | { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, | ||
4318 | {} | ||
4319 | }; | ||
4320 | |||
4321 | static struct pll_mapping nv40_pll_mapping[] = { | ||
4322 | { PLL_CORE , 0x004000 }, | ||
4323 | { PLL_MEMORY, 0x004020 }, | ||
4324 | { PLL_VPLL0 , NV_PRAMDAC_VPLL_COEFF }, | ||
4325 | { PLL_VPLL1 , NV_RAMDAC_VPLL2 }, | ||
4326 | {} | ||
4327 | }; | ||
4328 | |||
4329 | static struct pll_mapping nv50_pll_mapping[] = { | ||
4330 | { PLL_CORE , 0x004028 }, | ||
4331 | { PLL_SHADER, 0x004020 }, | ||
4332 | { PLL_UNK03 , 0x004000 }, | ||
4333 | { PLL_MEMORY, 0x004008 }, | ||
4334 | { PLL_UNK40 , 0x00e810 }, | ||
4335 | { PLL_UNK41 , 0x00e818 }, | ||
4336 | { PLL_UNK42 , 0x00e824 }, | ||
4337 | { PLL_VPLL0 , 0x614100 }, | ||
4338 | { PLL_VPLL1 , 0x614900 }, | ||
4339 | {} | ||
4340 | }; | ||
4341 | |||
4342 | static struct pll_mapping nv84_pll_mapping[] = { | ||
4343 | { PLL_CORE , 0x004028 }, | ||
4344 | { PLL_SHADER, 0x004020 }, | ||
4345 | { PLL_MEMORY, 0x004008 }, | ||
4346 | { PLL_VDEC , 0x004030 }, | ||
4347 | { PLL_UNK41 , 0x00e818 }, | ||
4348 | { PLL_VPLL0 , 0x614100 }, | ||
4349 | { PLL_VPLL1 , 0x614900 }, | ||
4350 | {} | ||
4351 | }; | ||
4352 | |||
4353 | u32 | ||
4354 | get_pll_register(struct drm_device *dev, enum pll_types type) | ||
4355 | { | ||
4356 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
4357 | struct nvbios *bios = &dev_priv->vbios; | ||
4358 | struct pll_mapping *map; | ||
4359 | int i; | ||
4360 | |||
4361 | if (dev_priv->card_type < NV_40) | ||
4362 | map = nv04_pll_mapping; | ||
4363 | else | ||
4364 | if (dev_priv->card_type < NV_50) | ||
4365 | map = nv40_pll_mapping; | ||
4366 | else { | ||
4367 | u8 *plim = &bios->data[bios->pll_limit_tbl_ptr]; | ||
4368 | |||
4369 | if (plim[0] >= 0x30) { | ||
4370 | u8 *entry = plim + plim[1]; | ||
4371 | for (i = 0; i < plim[3]; i++, entry += plim[2]) { | ||
4372 | if (entry[0] == type) | ||
4373 | return ROM32(entry[3]); | ||
4374 | } | ||
4375 | |||
4376 | return 0; | ||
4377 | } | ||
4378 | |||
4379 | if (dev_priv->chipset == 0x50) | ||
4380 | map = nv50_pll_mapping; | ||
4381 | else | ||
4382 | map = nv84_pll_mapping; | ||
4383 | } | ||
4384 | |||
4385 | while (map->reg) { | ||
4386 | if (map->type == type) | ||
4387 | return map->reg; | ||
4388 | map++; | ||
4389 | } | ||
4390 | |||
4391 | return 0; | ||
4392 | } | ||
4393 | |||
4394 | int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims *pll_lim) | ||
4395 | { | ||
4396 | /* | ||
4397 | * PLL limits table | ||
4398 | * | ||
4399 | * Version 0x10: NV30, NV31 | ||
4400 | * One byte header (version), one record of 24 bytes | ||
4401 | * Version 0x11: NV36 - Not implemented | ||
4402 | * Seems to have same record style as 0x10, but 3 records rather than 1 | ||
4403 | * Version 0x20: Found on Geforce 6 cards | ||
4404 | * Trivial 4 byte BIT header. 31 (0x1f) byte record length | ||
4405 | * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards | ||
4406 | * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record | ||
4407 | * length in general, some (integrated) have an extra configuration byte | ||
4408 | * Version 0x30: Found on Geforce 8, separates the register mapping | ||
4409 | * from the limits tables. | ||
4410 | */ | ||
4411 | |||
4412 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
4413 | struct nvbios *bios = &dev_priv->vbios; | ||
4414 | int cv = bios->chip_version, pllindex = 0; | ||
4415 | uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0; | ||
4416 | uint32_t crystal_strap_mask, crystal_straps; | ||
4417 | |||
4418 | if (!bios->pll_limit_tbl_ptr) { | ||
4419 | if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || | ||
4420 | cv >= 0x40) { | ||
4421 | NV_ERROR(dev, "Pointer to PLL limits table invalid\n"); | ||
4422 | return -EINVAL; | ||
4423 | } | ||
4424 | } else | ||
4425 | pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr]; | ||
4426 | |||
4427 | crystal_strap_mask = 1 << 6; | ||
4428 | /* open coded dev->twoHeads test */ | ||
4429 | if (cv > 0x10 && cv != 0x15 && cv != 0x1a && cv != 0x20) | ||
4430 | crystal_strap_mask |= 1 << 22; | ||
4431 | crystal_straps = nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & | ||
4432 | crystal_strap_mask; | ||
4433 | |||
4434 | switch (pll_lim_ver) { | ||
4435 | /* | ||
4436 | * We use version 0 to indicate a pre limit table bios (single stage | ||
4437 | * pll) and load the hard coded limits instead. | ||
4438 | */ | ||
4439 | case 0: | ||
4440 | break; | ||
4441 | case 0x10: | ||
4442 | case 0x11: | ||
4443 | /* | ||
4444 | * Strictly v0x11 has 3 entries, but the last two don't seem | ||
4445 | * to get used. | ||
4446 | */ | ||
4447 | headerlen = 1; | ||
4448 | recordlen = 0x18; | ||
4449 | entries = 1; | ||
4450 | pllindex = 0; | ||
4451 | break; | ||
4452 | case 0x20: | ||
4453 | case 0x21: | ||
4454 | case 0x30: | ||
4455 | case 0x40: | ||
4456 | headerlen = bios->data[bios->pll_limit_tbl_ptr + 1]; | ||
4457 | recordlen = bios->data[bios->pll_limit_tbl_ptr + 2]; | ||
4458 | entries = bios->data[bios->pll_limit_tbl_ptr + 3]; | ||
4459 | break; | ||
4460 | default: | ||
4461 | NV_ERROR(dev, "PLL limits table revision 0x%X not currently " | ||
4462 | "supported\n", pll_lim_ver); | ||
4463 | return -ENOSYS; | ||
4464 | } | ||
4465 | |||
4466 | /* initialize all members to zero */ | ||
4467 | memset(pll_lim, 0, sizeof(struct pll_lims)); | ||
4468 | |||
4469 | /* if we were passed a type rather than a register, figure | ||
4470 | * out the register and store it | ||
4471 | */ | ||
4472 | if (limit_match > PLL_MAX) | ||
4473 | pll_lim->reg = limit_match; | ||
4474 | else { | ||
4475 | pll_lim->reg = get_pll_register(dev, limit_match); | ||
4476 | if (!pll_lim->reg) | ||
4477 | return -ENOENT; | ||
4478 | } | ||
4479 | |||
4480 | if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { | ||
4481 | uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; | ||
4482 | |||
4483 | pll_lim->vco1.minfreq = ROM32(pll_rec[0]); | ||
4484 | pll_lim->vco1.maxfreq = ROM32(pll_rec[4]); | ||
4485 | pll_lim->vco2.minfreq = ROM32(pll_rec[8]); | ||
4486 | pll_lim->vco2.maxfreq = ROM32(pll_rec[12]); | ||
4487 | pll_lim->vco1.min_inputfreq = ROM32(pll_rec[16]); | ||
4488 | pll_lim->vco2.min_inputfreq = ROM32(pll_rec[20]); | ||
4489 | pll_lim->vco1.max_inputfreq = pll_lim->vco2.max_inputfreq = INT_MAX; | ||
4490 | |||
4491 | /* these values taken from nv30/31/36 */ | ||
4492 | pll_lim->vco1.min_n = 0x1; | ||
4493 | if (cv == 0x36) | ||
4494 | pll_lim->vco1.min_n = 0x5; | ||
4495 | pll_lim->vco1.max_n = 0xff; | ||
4496 | pll_lim->vco1.min_m = 0x1; | ||
4497 | pll_lim->vco1.max_m = 0xd; | ||
4498 | pll_lim->vco2.min_n = 0x4; | ||
4499 | /* | ||
4500 | * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this | ||
4501 | * table version (apart from nv35)), N2 is compared to | ||
4502 | * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and | ||
4503 | * save a comparison | ||
4504 | */ | ||
4505 | pll_lim->vco2.max_n = 0x28; | ||
4506 | if (cv == 0x30 || cv == 0x35) | ||
4507 | /* only 5 bits available for N2 on nv30/35 */ | ||
4508 | pll_lim->vco2.max_n = 0x1f; | ||
4509 | pll_lim->vco2.min_m = 0x1; | ||
4510 | pll_lim->vco2.max_m = 0x4; | ||
4511 | pll_lim->max_log2p = 0x7; | ||
4512 | pll_lim->max_usable_log2p = 0x6; | ||
4513 | } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { | ||
4514 | uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; | ||
4515 | uint8_t *pll_rec; | ||
4516 | int i; | ||
4517 | |||
4518 | /* | ||
4519 | * First entry is default match, if nothing better. warn if | ||
4520 | * reg field nonzero | ||
4521 | */ | ||
4522 | if (ROM32(bios->data[plloffs])) | ||
4523 | NV_WARN(dev, "Default PLL limit entry has non-zero " | ||
4524 | "register field\n"); | ||
4525 | |||
4526 | for (i = 1; i < entries; i++) | ||
4527 | if (ROM32(bios->data[plloffs + recordlen * i]) == pll_lim->reg) { | ||
4528 | pllindex = i; | ||
4529 | break; | ||
4530 | } | ||
4531 | |||
4532 | if ((dev_priv->card_type >= NV_50) && (pllindex == 0)) { | ||
4533 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | ||
4534 | "limits table", pll_lim->reg); | ||
4535 | return -ENOENT; | ||
4536 | } | ||
4537 | |||
4538 | pll_rec = &bios->data[plloffs + recordlen * pllindex]; | ||
4539 | |||
4540 | BIOSLOG(bios, "Loading PLL limits for reg 0x%08x\n", | ||
4541 | pllindex ? pll_lim->reg : 0); | ||
4542 | |||
4543 | /* | ||
4544 | * Frequencies are stored in tables in MHz, kHz are more | ||
4545 | * useful, so we convert. | ||
4546 | */ | ||
4547 | |||
4548 | /* What output frequencies can each VCO generate? */ | ||
4549 | pll_lim->vco1.minfreq = ROM16(pll_rec[4]) * 1000; | ||
4550 | pll_lim->vco1.maxfreq = ROM16(pll_rec[6]) * 1000; | ||
4551 | pll_lim->vco2.minfreq = ROM16(pll_rec[8]) * 1000; | ||
4552 | pll_lim->vco2.maxfreq = ROM16(pll_rec[10]) * 1000; | ||
4553 | |||
4554 | /* What input frequencies they accept (past the m-divider)? */ | ||
4555 | pll_lim->vco1.min_inputfreq = ROM16(pll_rec[12]) * 1000; | ||
4556 | pll_lim->vco2.min_inputfreq = ROM16(pll_rec[14]) * 1000; | ||
4557 | pll_lim->vco1.max_inputfreq = ROM16(pll_rec[16]) * 1000; | ||
4558 | pll_lim->vco2.max_inputfreq = ROM16(pll_rec[18]) * 1000; | ||
4559 | |||
4560 | /* What values are accepted as multiplier and divider? */ | ||
4561 | pll_lim->vco1.min_n = pll_rec[20]; | ||
4562 | pll_lim->vco1.max_n = pll_rec[21]; | ||
4563 | pll_lim->vco1.min_m = pll_rec[22]; | ||
4564 | pll_lim->vco1.max_m = pll_rec[23]; | ||
4565 | pll_lim->vco2.min_n = pll_rec[24]; | ||
4566 | pll_lim->vco2.max_n = pll_rec[25]; | ||
4567 | pll_lim->vco2.min_m = pll_rec[26]; | ||
4568 | pll_lim->vco2.max_m = pll_rec[27]; | ||
4569 | |||
4570 | pll_lim->max_usable_log2p = pll_lim->max_log2p = pll_rec[29]; | ||
4571 | if (pll_lim->max_log2p > 0x7) | ||
4572 | /* pll decoding in nv_hw.c assumes never > 7 */ | ||
4573 | NV_WARN(dev, "Max log2 P value greater than 7 (%d)\n", | ||
4574 | pll_lim->max_log2p); | ||
4575 | if (cv < 0x60) | ||
4576 | pll_lim->max_usable_log2p = 0x6; | ||
4577 | pll_lim->log2p_bias = pll_rec[30]; | ||
4578 | |||
4579 | if (recordlen > 0x22) | ||
4580 | pll_lim->refclk = ROM32(pll_rec[31]); | ||
4581 | |||
4582 | if (recordlen > 0x23 && pll_rec[35]) | ||
4583 | NV_WARN(dev, | ||
4584 | "Bits set in PLL configuration byte (%x)\n", | ||
4585 | pll_rec[35]); | ||
4586 | |||
4587 | /* C51 special not seen elsewhere */ | ||
4588 | if (cv == 0x51 && !pll_lim->refclk) { | ||
4589 | uint32_t sel_clk = bios_rd32(bios, NV_PRAMDAC_SEL_CLK); | ||
4590 | |||
4591 | if ((pll_lim->reg == NV_PRAMDAC_VPLL_COEFF && sel_clk & 0x20) || | ||
4592 | (pll_lim->reg == NV_RAMDAC_VPLL2 && sel_clk & 0x80)) { | ||
4593 | if (bios_idxprt_rd(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) | ||
4594 | pll_lim->refclk = 200000; | ||
4595 | else | ||
4596 | pll_lim->refclk = 25000; | ||
4597 | } | ||
4598 | } | ||
4599 | } else if (pll_lim_ver == 0x30) { /* ver 0x30 */ | ||
4600 | uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen]; | ||
4601 | uint8_t *record = NULL; | ||
4602 | int i; | ||
4603 | |||
4604 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", | ||
4605 | pll_lim->reg); | ||
4606 | |||
4607 | for (i = 0; i < entries; i++, entry += recordlen) { | ||
4608 | if (ROM32(entry[3]) == pll_lim->reg) { | ||
4609 | record = &bios->data[ROM16(entry[1])]; | ||
4610 | break; | ||
4611 | } | ||
4612 | } | ||
4613 | |||
4614 | if (!record) { | ||
4615 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | ||
4616 | "limits table", pll_lim->reg); | ||
4617 | return -ENOENT; | ||
4618 | } | ||
4619 | |||
4620 | pll_lim->vco1.minfreq = ROM16(record[0]) * 1000; | ||
4621 | pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000; | ||
4622 | pll_lim->vco2.minfreq = ROM16(record[4]) * 1000; | ||
4623 | pll_lim->vco2.maxfreq = ROM16(record[6]) * 1000; | ||
4624 | pll_lim->vco1.min_inputfreq = ROM16(record[8]) * 1000; | ||
4625 | pll_lim->vco2.min_inputfreq = ROM16(record[10]) * 1000; | ||
4626 | pll_lim->vco1.max_inputfreq = ROM16(record[12]) * 1000; | ||
4627 | pll_lim->vco2.max_inputfreq = ROM16(record[14]) * 1000; | ||
4628 | pll_lim->vco1.min_n = record[16]; | ||
4629 | pll_lim->vco1.max_n = record[17]; | ||
4630 | pll_lim->vco1.min_m = record[18]; | ||
4631 | pll_lim->vco1.max_m = record[19]; | ||
4632 | pll_lim->vco2.min_n = record[20]; | ||
4633 | pll_lim->vco2.max_n = record[21]; | ||
4634 | pll_lim->vco2.min_m = record[22]; | ||
4635 | pll_lim->vco2.max_m = record[23]; | ||
4636 | pll_lim->max_usable_log2p = pll_lim->max_log2p = record[25]; | ||
4637 | pll_lim->log2p_bias = record[27]; | ||
4638 | pll_lim->refclk = ROM32(record[28]); | ||
4639 | } else if (pll_lim_ver) { /* ver 0x40 */ | ||
4640 | uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen]; | ||
4641 | uint8_t *record = NULL; | ||
4642 | int i; | ||
4643 | |||
4644 | BIOSLOG(bios, "Loading PLL limits for register 0x%08x\n", | ||
4645 | pll_lim->reg); | ||
4646 | |||
4647 | for (i = 0; i < entries; i++, entry += recordlen) { | ||
4648 | if (ROM32(entry[3]) == pll_lim->reg) { | ||
4649 | record = &bios->data[ROM16(entry[1])]; | ||
4650 | break; | ||
4651 | } | ||
4652 | } | ||
4653 | |||
4654 | if (!record) { | ||
4655 | NV_ERROR(dev, "Register 0x%08x not found in PLL " | ||
4656 | "limits table", pll_lim->reg); | ||
4657 | return -ENOENT; | ||
4658 | } | ||
4659 | |||
4660 | pll_lim->vco1.minfreq = ROM16(record[0]) * 1000; | ||
4661 | pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000; | ||
4662 | pll_lim->vco1.min_inputfreq = ROM16(record[4]) * 1000; | ||
4663 | pll_lim->vco1.max_inputfreq = ROM16(record[6]) * 1000; | ||
4664 | pll_lim->vco1.min_m = record[8]; | ||
4665 | pll_lim->vco1.max_m = record[9]; | ||
4666 | pll_lim->vco1.min_n = record[10]; | ||
4667 | pll_lim->vco1.max_n = record[11]; | ||
4668 | pll_lim->min_p = record[12]; | ||
4669 | pll_lim->max_p = record[13]; | ||
4670 | pll_lim->refclk = ROM16(entry[9]) * 1000; | ||
4671 | } | ||
4672 | |||
4673 | /* | ||
4674 | * By now any valid limit table ought to have set a max frequency for | ||
4675 | * vco1, so if it's zero it's either a pre limit table bios, or one | ||
4676 | * with an empty limit table (seen on nv18) | ||
4677 | */ | ||
4678 | if (!pll_lim->vco1.maxfreq) { | ||
4679 | pll_lim->vco1.minfreq = bios->fminvco; | ||
4680 | pll_lim->vco1.maxfreq = bios->fmaxvco; | ||
4681 | pll_lim->vco1.min_inputfreq = 0; | ||
4682 | pll_lim->vco1.max_inputfreq = INT_MAX; | ||
4683 | pll_lim->vco1.min_n = 0x1; | ||
4684 | pll_lim->vco1.max_n = 0xff; | ||
4685 | pll_lim->vco1.min_m = 0x1; | ||
4686 | if (crystal_straps == 0) { | ||
4687 | /* nv05 does this, nv11 doesn't, nv10 unknown */ | ||
4688 | if (cv < 0x11) | ||
4689 | pll_lim->vco1.min_m = 0x7; | ||
4690 | pll_lim->vco1.max_m = 0xd; | ||
4691 | } else { | ||
4692 | if (cv < 0x11) | ||
4693 | pll_lim->vco1.min_m = 0x8; | ||
4694 | pll_lim->vco1.max_m = 0xe; | ||
4695 | } | ||
4696 | if (cv < 0x17 || cv == 0x1a || cv == 0x20) | ||
4697 | pll_lim->max_log2p = 4; | ||
4698 | else | ||
4699 | pll_lim->max_log2p = 5; | ||
4700 | pll_lim->max_usable_log2p = pll_lim->max_log2p; | ||
4701 | } | ||
4702 | |||
4703 | if (!pll_lim->refclk) | ||
4704 | switch (crystal_straps) { | ||
4705 | case 0: | ||
4706 | pll_lim->refclk = 13500; | ||
4707 | break; | ||
4708 | case (1 << 6): | ||
4709 | pll_lim->refclk = 14318; | ||
4710 | break; | ||
4711 | case (1 << 22): | ||
4712 | pll_lim->refclk = 27000; | ||
4713 | break; | ||
4714 | case (1 << 22 | 1 << 6): | ||
4715 | pll_lim->refclk = 25000; | ||
4716 | break; | ||
4717 | } | ||
4718 | |||
4719 | NV_DEBUG(dev, "pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq); | ||
4720 | NV_DEBUG(dev, "pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq); | ||
4721 | NV_DEBUG(dev, "pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq); | ||
4722 | NV_DEBUG(dev, "pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq); | ||
4723 | NV_DEBUG(dev, "pll.vco1.min_n: %d\n", pll_lim->vco1.min_n); | ||
4724 | NV_DEBUG(dev, "pll.vco1.max_n: %d\n", pll_lim->vco1.max_n); | ||
4725 | NV_DEBUG(dev, "pll.vco1.min_m: %d\n", pll_lim->vco1.min_m); | ||
4726 | NV_DEBUG(dev, "pll.vco1.max_m: %d\n", pll_lim->vco1.max_m); | ||
4727 | if (pll_lim->vco2.maxfreq) { | ||
4728 | NV_DEBUG(dev, "pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq); | ||
4729 | NV_DEBUG(dev, "pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq); | ||
4730 | NV_DEBUG(dev, "pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq); | ||
4731 | NV_DEBUG(dev, "pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq); | ||
4732 | NV_DEBUG(dev, "pll.vco2.min_n: %d\n", pll_lim->vco2.min_n); | ||
4733 | NV_DEBUG(dev, "pll.vco2.max_n: %d\n", pll_lim->vco2.max_n); | ||
4734 | NV_DEBUG(dev, "pll.vco2.min_m: %d\n", pll_lim->vco2.min_m); | ||
4735 | NV_DEBUG(dev, "pll.vco2.max_m: %d\n", pll_lim->vco2.max_m); | ||
4736 | } | ||
4737 | if (!pll_lim->max_p) { | ||
4738 | NV_DEBUG(dev, "pll.max_log2p: %d\n", pll_lim->max_log2p); | ||
4739 | NV_DEBUG(dev, "pll.log2p_bias: %d\n", pll_lim->log2p_bias); | ||
4740 | } else { | ||
4741 | NV_DEBUG(dev, "pll.min_p: %d\n", pll_lim->min_p); | ||
4742 | NV_DEBUG(dev, "pll.max_p: %d\n", pll_lim->max_p); | ||
4743 | } | ||
4744 | NV_DEBUG(dev, "pll.refclk: %d\n", pll_lim->refclk); | ||
4745 | |||
4746 | return 0; | ||
4747 | } | ||
4748 | |||
4749 | static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset) | 4244 | static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset) |
4750 | { | 4245 | { |
4751 | /* | 4246 | /* |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 52fce11e9d26..e9bb14ec8c3b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -144,58 +144,6 @@ enum LVDS_script { | |||
144 | LVDS_PANEL_OFF | 144 | LVDS_PANEL_OFF |
145 | }; | 145 | }; |
146 | 146 | ||
147 | /* these match types in pll limits table version 0x40, | ||
148 | * nouveau uses them on all chipsets internally where a | ||
149 | * specific pll needs to be referenced, but the exact | ||
150 | * register isn't known. | ||
151 | */ | ||
152 | enum pll_types { | ||
153 | PLL_CORE = 0x01, | ||
154 | PLL_SHADER = 0x02, | ||
155 | PLL_UNK03 = 0x03, | ||
156 | PLL_MEMORY = 0x04, | ||
157 | PLL_VDEC = 0x05, | ||
158 | PLL_UNK40 = 0x40, | ||
159 | PLL_UNK41 = 0x41, | ||
160 | PLL_UNK42 = 0x42, | ||
161 | PLL_VPLL0 = 0x80, | ||
162 | PLL_VPLL1 = 0x81, | ||
163 | PLL_MAX = 0xff | ||
164 | }; | ||
165 | |||
166 | struct pll_lims { | ||
167 | u32 reg; | ||
168 | |||
169 | struct { | ||
170 | int minfreq; | ||
171 | int maxfreq; | ||
172 | int min_inputfreq; | ||
173 | int max_inputfreq; | ||
174 | |||
175 | uint8_t min_m; | ||
176 | uint8_t max_m; | ||
177 | uint8_t min_n; | ||
178 | uint8_t max_n; | ||
179 | } vco1, vco2; | ||
180 | |||
181 | uint8_t max_log2p; | ||
182 | /* | ||
183 | * for most pre nv50 cards setting a log2P of 7 (the common max_log2p | ||
184 | * value) is no different to 6 (at least for vplls) so allowing the MNP | ||
185 | * calc to use 7 causes the generated clock to be out by a factor of 2. | ||
186 | * however, max_log2p cannot be fixed-up during parsing as the | ||
187 | * unmodified max_log2p value is still needed for setting mplls, hence | ||
188 | * an additional max_usable_log2p member | ||
189 | */ | ||
190 | uint8_t max_usable_log2p; | ||
191 | uint8_t log2p_bias; | ||
192 | |||
193 | uint8_t min_p; | ||
194 | uint8_t max_p; | ||
195 | |||
196 | int refclk; | ||
197 | }; | ||
198 | |||
199 | struct nvbios { | 147 | struct nvbios { |
200 | struct drm_device *dev; | 148 | struct drm_device *dev; |
201 | enum { | 149 | enum { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c index dad96cce5e39..5b487655d6b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_calc.c +++ b/drivers/gpu/drm/nouveau/nouveau_calc.c | |||
@@ -260,219 +260,3 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm | |||
260 | } else | 260 | } else |
261 | nv20_update_arb(burst, lwm); | 261 | nv20_update_arb(burst, lwm); |
262 | } | 262 | } |
263 | |||
264 | static int | ||
265 | getMNP_single(struct drm_device *dev, struct pll_lims *pll_lim, int clk, | ||
266 | struct nouveau_pll_vals *bestpv) | ||
267 | { | ||
268 | /* Find M, N and P for a single stage PLL | ||
269 | * | ||
270 | * Note that some bioses (NV3x) have lookup tables of precomputed MNP | ||
271 | * values, but we're too lazy to use those atm | ||
272 | * | ||
273 | * "clk" parameter in kHz | ||
274 | * returns calculated clock | ||
275 | */ | ||
276 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
277 | int cv = dev_priv->vbios.chip_version; | ||
278 | int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq; | ||
279 | int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m; | ||
280 | int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n; | ||
281 | int minU = pll_lim->vco1.min_inputfreq; | ||
282 | int maxU = pll_lim->vco1.max_inputfreq; | ||
283 | int minP = pll_lim->max_p ? pll_lim->min_p : 0; | ||
284 | int maxP = pll_lim->max_p ? pll_lim->max_p : pll_lim->max_usable_log2p; | ||
285 | int crystal = pll_lim->refclk; | ||
286 | int M, N, thisP, P; | ||
287 | int clkP, calcclk; | ||
288 | int delta, bestdelta = INT_MAX; | ||
289 | int bestclk = 0; | ||
290 | |||
291 | /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */ | ||
292 | /* possibly correlated with introduction of 27MHz crystal */ | ||
293 | if (dev_priv->card_type < NV_50) { | ||
294 | if (cv < 0x17 || cv == 0x1a || cv == 0x20) { | ||
295 | if (clk > 250000) | ||
296 | maxM = 6; | ||
297 | if (clk > 340000) | ||
298 | maxM = 2; | ||
299 | } else if (cv < 0x40) { | ||
300 | if (clk > 150000) | ||
301 | maxM = 6; | ||
302 | if (clk > 200000) | ||
303 | maxM = 4; | ||
304 | if (clk > 340000) | ||
305 | maxM = 2; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | P = pll_lim->max_p ? maxP : (1 << maxP); | ||
310 | if ((clk * P) < minvco) { | ||
311 | minvco = clk * maxP; | ||
312 | maxvco = minvco * 2; | ||
313 | } | ||
314 | |||
315 | if (clk + clk/200 > maxvco) /* +0.5% */ | ||
316 | maxvco = clk + clk/200; | ||
317 | |||
318 | /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */ | ||
319 | for (thisP = minP; thisP <= maxP; thisP++) { | ||
320 | P = pll_lim->max_p ? thisP : (1 << thisP); | ||
321 | clkP = clk * P; | ||
322 | |||
323 | if (clkP < minvco) | ||
324 | continue; | ||
325 | if (clkP > maxvco) | ||
326 | return bestclk; | ||
327 | |||
328 | for (M = minM; M <= maxM; M++) { | ||
329 | if (crystal/M < minU) | ||
330 | return bestclk; | ||
331 | if (crystal/M > maxU) | ||
332 | continue; | ||
333 | |||
334 | /* add crystal/2 to round better */ | ||
335 | N = (clkP * M + crystal/2) / crystal; | ||
336 | |||
337 | if (N < minN) | ||
338 | continue; | ||
339 | if (N > maxN) | ||
340 | break; | ||
341 | |||
342 | /* more rounding additions */ | ||
343 | calcclk = ((N * crystal + P/2) / P + M/2) / M; | ||
344 | delta = abs(calcclk - clk); | ||
345 | /* we do an exhaustive search rather than terminating | ||
346 | * on an optimality condition... | ||
347 | */ | ||
348 | if (delta < bestdelta) { | ||
349 | bestdelta = delta; | ||
350 | bestclk = calcclk; | ||
351 | bestpv->N1 = N; | ||
352 | bestpv->M1 = M; | ||
353 | bestpv->log2P = thisP; | ||
354 | if (delta == 0) /* except this one */ | ||
355 | return bestclk; | ||
356 | } | ||
357 | } | ||
358 | } | ||
359 | |||
360 | return bestclk; | ||
361 | } | ||
362 | |||
363 | static int | ||
364 | getMNP_double(struct drm_device *dev, struct pll_lims *pll_lim, int clk, | ||
365 | struct nouveau_pll_vals *bestpv) | ||
366 | { | ||
367 | /* Find M, N and P for a two stage PLL | ||
368 | * | ||
369 | * Note that some bioses (NV30+) have lookup tables of precomputed MNP | ||
370 | * values, but we're too lazy to use those atm | ||
371 | * | ||
372 | * "clk" parameter in kHz | ||
373 | * returns calculated clock | ||
374 | */ | ||
375 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
376 | int chip_version = dev_priv->vbios.chip_version; | ||
377 | int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq; | ||
378 | int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq; | ||
379 | int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq; | ||
380 | int maxU1 = pll_lim->vco1.max_inputfreq, maxU2 = pll_lim->vco2.max_inputfreq; | ||
381 | int minM1 = pll_lim->vco1.min_m, maxM1 = pll_lim->vco1.max_m; | ||
382 | int minN1 = pll_lim->vco1.min_n, maxN1 = pll_lim->vco1.max_n; | ||
383 | int minM2 = pll_lim->vco2.min_m, maxM2 = pll_lim->vco2.max_m; | ||
384 | int minN2 = pll_lim->vco2.min_n, maxN2 = pll_lim->vco2.max_n; | ||
385 | int maxlog2P = pll_lim->max_usable_log2p; | ||
386 | int crystal = pll_lim->refclk; | ||
387 | bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2); | ||
388 | int M1, N1, M2, N2, log2P; | ||
389 | int clkP, calcclk1, calcclk2, calcclkout; | ||
390 | int delta, bestdelta = INT_MAX; | ||
391 | int bestclk = 0; | ||
392 | |||
393 | int vco2 = (maxvco2 - maxvco2/200) / 2; | ||
394 | for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++) | ||
395 | ; | ||
396 | clkP = clk << log2P; | ||
397 | |||
398 | if (maxvco2 < clk + clk/200) /* +0.5% */ | ||
399 | maxvco2 = clk + clk/200; | ||
400 | |||
401 | for (M1 = minM1; M1 <= maxM1; M1++) { | ||
402 | if (crystal/M1 < minU1) | ||
403 | return bestclk; | ||
404 | if (crystal/M1 > maxU1) | ||
405 | continue; | ||
406 | |||
407 | for (N1 = minN1; N1 <= maxN1; N1++) { | ||
408 | calcclk1 = crystal * N1 / M1; | ||
409 | if (calcclk1 < minvco1) | ||
410 | continue; | ||
411 | if (calcclk1 > maxvco1) | ||
412 | break; | ||
413 | |||
414 | for (M2 = minM2; M2 <= maxM2; M2++) { | ||
415 | if (calcclk1/M2 < minU2) | ||
416 | break; | ||
417 | if (calcclk1/M2 > maxU2) | ||
418 | continue; | ||
419 | |||
420 | /* add calcclk1/2 to round better */ | ||
421 | N2 = (clkP * M2 + calcclk1/2) / calcclk1; | ||
422 | if (N2 < minN2) | ||
423 | continue; | ||
424 | if (N2 > maxN2) | ||
425 | break; | ||
426 | |||
427 | if (!fixedgain2) { | ||
428 | if (chip_version < 0x60) | ||
429 | if (N2/M2 < 4 || N2/M2 > 10) | ||
430 | continue; | ||
431 | |||
432 | calcclk2 = calcclk1 * N2 / M2; | ||
433 | if (calcclk2 < minvco2) | ||
434 | break; | ||
435 | if (calcclk2 > maxvco2) | ||
436 | continue; | ||
437 | } else | ||
438 | calcclk2 = calcclk1; | ||
439 | |||
440 | calcclkout = calcclk2 >> log2P; | ||
441 | delta = abs(calcclkout - clk); | ||
442 | /* we do an exhaustive search rather than terminating | ||
443 | * on an optimality condition... | ||
444 | */ | ||
445 | if (delta < bestdelta) { | ||
446 | bestdelta = delta; | ||
447 | bestclk = calcclkout; | ||
448 | bestpv->N1 = N1; | ||
449 | bestpv->M1 = M1; | ||
450 | bestpv->N2 = N2; | ||
451 | bestpv->M2 = M2; | ||
452 | bestpv->log2P = log2P; | ||
453 | if (delta == 0) /* except this one */ | ||
454 | return bestclk; | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | |||
460 | return bestclk; | ||
461 | } | ||
462 | |||
463 | int | ||
464 | nouveau_calc_pll_mnp(struct drm_device *dev, struct pll_lims *pll_lim, int clk, | ||
465 | struct nouveau_pll_vals *pv) | ||
466 | { | ||
467 | int outclk; | ||
468 | |||
469 | if (!pll_lim->vco2.maxfreq) | ||
470 | outclk = getMNP_single(dev, pll_lim, clk, pv); | ||
471 | else | ||
472 | outclk = getMNP_double(dev, pll_lim, clk, pv); | ||
473 | |||
474 | if (!outclk) | ||
475 | NV_ERROR(dev, "Could not find a compatible set of PLL values\n"); | ||
476 | |||
477 | return outclk; | ||
478 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.c b/drivers/gpu/drm/nouveau/nouveau_compat.c index 76582b0a9df8..30431c820bb3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.c +++ b/drivers/gpu/drm/nouveau/nouveau_compat.c | |||
@@ -2,8 +2,10 @@ | |||
2 | #include "nouveau_compat.h" | 2 | #include "nouveau_compat.h" |
3 | 3 | ||
4 | #include <subdev/bios.h> | 4 | #include <subdev/bios.h> |
5 | #include <subdev/bios/pll.h> | ||
5 | #include <subdev/gpio.h> | 6 | #include <subdev/gpio.h> |
6 | #include <subdev/i2c.h> | 7 | #include <subdev/i2c.h> |
8 | #include <subdev/clock.h> | ||
7 | 9 | ||
8 | void *nouveau_newpriv(struct drm_device *); | 10 | void *nouveau_newpriv(struct drm_device *); |
9 | 11 | ||
@@ -180,3 +182,76 @@ auxch_wr(struct drm_device *dev, struct nouveau_i2c_port *port, | |||
180 | { | 182 | { |
181 | return nv_wraux(port, addr, data, size); | 183 | return nv_wraux(port, addr, data, size); |
182 | } | 184 | } |
185 | |||
186 | u32 | ||
187 | get_pll_register(struct drm_device *dev, u32 type) | ||
188 | { | ||
189 | struct nouveau_drm *drm = nouveau_newpriv(dev); | ||
190 | struct nouveau_bios *bios = nouveau_bios(drm->device); | ||
191 | struct nvbios_pll info; | ||
192 | |||
193 | if (nvbios_pll_parse(bios, type, &info)) | ||
194 | return 0; | ||
195 | return info.reg; | ||
196 | } | ||
197 | |||
198 | int | ||
199 | get_pll_limits(struct drm_device *dev, u32 type, struct nvbios_pll *info) | ||
200 | { | ||
201 | struct nouveau_drm *drm = nouveau_newpriv(dev); | ||
202 | struct nouveau_bios *bios = nouveau_bios(drm->device); | ||
203 | |||
204 | return nvbios_pll_parse(bios, type, info); | ||
205 | } | ||
206 | |||
207 | int | ||
208 | setPLL(struct drm_device *dev, u32 reg, u32 freq) | ||
209 | { | ||
210 | struct nouveau_drm *drm = nouveau_newpriv(dev); | ||
211 | struct nouveau_clock *clk = nouveau_clock(drm->device); | ||
212 | int ret = -ENODEV; | ||
213 | |||
214 | if (clk->pll_set) | ||
215 | ret = clk->pll_set(clk, reg, freq); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | |||
220 | int | ||
221 | nouveau_calc_pll_mnp(struct drm_device *dev, struct nvbios_pll *info, | ||
222 | int freq, struct nouveau_pll_vals *pv) | ||
223 | { | ||
224 | struct nouveau_drm *drm = nouveau_newpriv(dev); | ||
225 | struct nouveau_clock *clk = nouveau_clock(drm->device); | ||
226 | int ret = 0; | ||
227 | |||
228 | if (clk->pll_calc) | ||
229 | ret = clk->pll_calc(clk, info, freq, pv); | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | int | ||
234 | nouveau_hw_setpll(struct drm_device *dev, u32 reg1, | ||
235 | struct nouveau_pll_vals *pv) | ||
236 | { | ||
237 | struct nouveau_drm *drm = nouveau_newpriv(dev); | ||
238 | struct nouveau_clock *clk = nouveau_clock(drm->device); | ||
239 | int ret = -ENODEV; | ||
240 | |||
241 | if (clk->pll_prog) | ||
242 | ret = clk->pll_prog(clk, reg1, pv); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, | ||
247 | int *N, int *fN, int *M, int *P); | ||
248 | |||
249 | int | ||
250 | nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, | ||
251 | int *N, int *fN, int *M, int *P) | ||
252 | { | ||
253 | struct nouveau_drm *drm = nouveau_newpriv(dev); | ||
254 | struct nouveau_clock *clk = nouveau_clock(drm->device); | ||
255 | |||
256 | return nva3_pll_calc(clk, info, freq, N, fN, M, P); | ||
257 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_compat.h b/drivers/gpu/drm/nouveau/nouveau_compat.h index 9b3298bfe4ed..8bf5bec81710 100644 --- a/drivers/gpu/drm/nouveau/nouveau_compat.h +++ b/drivers/gpu/drm/nouveau/nouveau_compat.h | |||
@@ -32,5 +32,17 @@ int nouveau_i2c_identify(struct drm_device *dev, const char *what, | |||
32 | int auxch_rd(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); | 32 | int auxch_rd(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); |
33 | int auxch_wr(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); | 33 | int auxch_wr(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); |
34 | 34 | ||
35 | struct nvbios_pll; | ||
36 | struct nouveau_pll_vals; | ||
37 | |||
38 | u32 get_pll_register(struct drm_device *dev, u32 type); | ||
39 | int get_pll_limits(struct drm_device *, u32, struct nvbios_pll *); | ||
40 | int setPLL(struct drm_device *, u32 reg, u32 clk); | ||
41 | |||
42 | int nouveau_calc_pll_mnp(struct drm_device *, struct nvbios_pll *, | ||
43 | int, struct nouveau_pll_vals *); | ||
44 | int nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, | ||
45 | int *N, int *fN, int *M, int *P); | ||
46 | int nouveau_hw_setpll(struct drm_device *, u32, struct nouveau_pll_vals *); | ||
35 | 47 | ||
36 | #endif | 48 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index afe978702097..2b519b5cfac9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -68,6 +68,9 @@ struct nouveau_grctx; | |||
68 | struct nouveau_mem; | 68 | struct nouveau_mem; |
69 | #include <subdev/vm.h> | 69 | #include <subdev/vm.h> |
70 | 70 | ||
71 | #include <subdev/bios/pll.h> | ||
72 | #include "nouveau_compat.h" | ||
73 | |||
71 | #define MAX_NUM_DCB_ENTRIES 16 | 74 | #define MAX_NUM_DCB_ENTRIES 16 |
72 | 75 | ||
73 | #define NOUVEAU_MAX_CHANNEL_NR 4096 | 76 | #define NOUVEAU_MAX_CHANNEL_NR 4096 |
@@ -549,24 +552,6 @@ struct nouveau_engine { | |||
549 | struct nouveau_vram_engine vram; | 552 | struct nouveau_vram_engine vram; |
550 | }; | 553 | }; |
551 | 554 | ||
552 | struct nouveau_pll_vals { | ||
553 | union { | ||
554 | struct { | ||
555 | #ifdef __BIG_ENDIAN | ||
556 | uint8_t N1, M1, N2, M2; | ||
557 | #else | ||
558 | uint8_t M1, N1, M2, N2; | ||
559 | #endif | ||
560 | }; | ||
561 | struct { | ||
562 | uint16_t NM1, NM2; | ||
563 | } __attribute__((packed)); | ||
564 | }; | ||
565 | int log2P; | ||
566 | |||
567 | int refclk; | ||
568 | }; | ||
569 | |||
570 | enum nv04_fp_display_regs { | 555 | enum nv04_fp_display_regs { |
571 | FP_DISPLAY_END, | 556 | FP_DISPLAY_END, |
572 | FP_TOTAL, | 557 | FP_TOTAL, |
@@ -1060,9 +1045,6 @@ extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, | |||
1060 | extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); | 1045 | extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); |
1061 | extern struct dcb_connector_table_entry * | 1046 | extern struct dcb_connector_table_entry * |
1062 | nouveau_bios_connector_entry(struct drm_device *, int index); | 1047 | nouveau_bios_connector_entry(struct drm_device *, int index); |
1063 | extern u32 get_pll_register(struct drm_device *, enum pll_types); | ||
1064 | extern int get_pll_limits(struct drm_device *, uint32_t limit_match, | ||
1065 | struct pll_lims *); | ||
1066 | extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, | 1048 | extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, |
1067 | struct dcb_entry *, int crtc); | 1049 | struct dcb_entry *, int crtc); |
1068 | extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); | 1050 | extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); |
@@ -1365,12 +1347,6 @@ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, | |||
1365 | int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, | 1347 | int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, |
1366 | uint32_t handle); | 1348 | uint32_t handle); |
1367 | 1349 | ||
1368 | /* nv50_calc.c */ | ||
1369 | int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, | ||
1370 | int *N1, int *M1, int *N2, int *M2, int *P); | ||
1371 | int nva3_calc_pll(struct drm_device *, struct pll_lims *, | ||
1372 | int clk, int *N, int *fN, int *M, int *P); | ||
1373 | |||
1374 | #ifndef ioread32_native | 1350 | #ifndef ioread32_native |
1375 | #ifdef __BIG_ENDIAN | 1351 | #ifdef __BIG_ENDIAN |
1376 | #define ioread16_native ioread16be | 1352 | #define ioread16_native ioread16be |
@@ -1398,7 +1374,6 @@ static inline void nvchan_wr32(struct nouveau_channel *chan, | |||
1398 | } | 1374 | } |
1399 | 1375 | ||
1400 | /* register access */ | 1376 | /* register access */ |
1401 | #include "nouveau_compat.h" | ||
1402 | #define nv_rd08 _nv_rd08 | 1377 | #define nv_rd08 _nv_rd08 |
1403 | #define nv_wr08 _nv_wr08 | 1378 | #define nv_wr08 _nv_wr08 |
1404 | #define nv_rd32 _nv_rd32 | 1379 | #define nv_rd32 _nv_rd32 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index b87ad3bd7739..fdd667b70528 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "nouveau_drv.h" | 26 | #include "nouveau_drv.h" |
27 | #include "nouveau_hw.h" | 27 | #include "nouveau_hw.h" |
28 | 28 | ||
29 | #include <subdev/bios/pll.h> | ||
30 | |||
29 | #define CHIPSET_NFORCE 0x01a0 | 31 | #define CHIPSET_NFORCE 0x01a0 |
30 | #define CHIPSET_NFORCE2 0x01f0 | 32 | #define CHIPSET_NFORCE2 0x01f0 |
31 | 33 | ||
@@ -123,270 +125,6 @@ NVBlankScreen(struct drm_device *dev, int head, bool blank) | |||
123 | } | 125 | } |
124 | 126 | ||
125 | /* | 127 | /* |
126 | * PLL setting | ||
127 | */ | ||
128 | |||
129 | static int | ||
130 | powerctrl_1_shift(int chip_version, int reg) | ||
131 | { | ||
132 | int shift = -4; | ||
133 | |||
134 | if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20) | ||
135 | return shift; | ||
136 | |||
137 | switch (reg) { | ||
138 | case NV_RAMDAC_VPLL2: | ||
139 | shift += 4; | ||
140 | case NV_PRAMDAC_VPLL_COEFF: | ||
141 | shift += 4; | ||
142 | case NV_PRAMDAC_MPLL_COEFF: | ||
143 | shift += 4; | ||
144 | case NV_PRAMDAC_NVPLL_COEFF: | ||
145 | shift += 4; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * the shift for vpll regs is only used for nv3x chips with a single | ||
150 | * stage pll | ||
151 | */ | ||
152 | if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 || | ||
153 | chip_version == 0x36 || chip_version >= 0x40)) | ||
154 | shift = -4; | ||
155 | |||
156 | return shift; | ||
157 | } | ||
158 | |||
159 | static void | ||
160 | setPLL_single(struct drm_device *dev, uint32_t reg, struct nouveau_pll_vals *pv) | ||
161 | { | ||
162 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
163 | int chip_version = dev_priv->vbios.chip_version; | ||
164 | uint32_t oldpll = NVReadRAMDAC(dev, 0, reg); | ||
165 | int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; | ||
166 | uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; | ||
167 | uint32_t saved_powerctrl_1 = 0; | ||
168 | int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg); | ||
169 | |||
170 | if (oldpll == pll) | ||
171 | return; /* already set */ | ||
172 | |||
173 | if (shift_powerctrl_1 >= 0) { | ||
174 | saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1); | ||
175 | nvWriteMC(dev, NV_PBUS_POWERCTRL_1, | ||
176 | (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | | ||
177 | 1 << shift_powerctrl_1); | ||
178 | } | ||
179 | |||
180 | if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) | ||
181 | /* upclock -- write new post divider first */ | ||
182 | NVWriteRAMDAC(dev, 0, reg, pv->log2P << 16 | (oldpll & 0xffff)); | ||
183 | else | ||
184 | /* downclock -- write new NM first */ | ||
185 | NVWriteRAMDAC(dev, 0, reg, (oldpll & 0xffff0000) | pv->NM1); | ||
186 | |||
187 | if (chip_version < 0x17 && chip_version != 0x11) | ||
188 | /* wait a bit on older chips */ | ||
189 | msleep(64); | ||
190 | NVReadRAMDAC(dev, 0, reg); | ||
191 | |||
192 | /* then write the other half as well */ | ||
193 | NVWriteRAMDAC(dev, 0, reg, pll); | ||
194 | |||
195 | if (shift_powerctrl_1 >= 0) | ||
196 | nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); | ||
197 | } | ||
198 | |||
199 | static uint32_t | ||
200 | new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) | ||
201 | { | ||
202 | bool head_a = (reg1 == NV_PRAMDAC_VPLL_COEFF); | ||
203 | |||
204 | if (ss) /* single stage pll mode */ | ||
205 | ramdac580 |= head_a ? NV_RAMDAC_580_VPLL1_ACTIVE : | ||
206 | NV_RAMDAC_580_VPLL2_ACTIVE; | ||
207 | else | ||
208 | ramdac580 &= head_a ? ~NV_RAMDAC_580_VPLL1_ACTIVE : | ||
209 | ~NV_RAMDAC_580_VPLL2_ACTIVE; | ||
210 | |||
211 | return ramdac580; | ||
212 | } | ||
213 | |||
214 | static void | ||
215 | setPLL_double_highregs(struct drm_device *dev, uint32_t reg1, | ||
216 | struct nouveau_pll_vals *pv) | ||
217 | { | ||
218 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
219 | int chip_version = dev_priv->vbios.chip_version; | ||
220 | bool nv3035 = chip_version == 0x30 || chip_version == 0x35; | ||
221 | uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70); | ||
222 | uint32_t oldpll1 = NVReadRAMDAC(dev, 0, reg1); | ||
223 | uint32_t oldpll2 = !nv3035 ? NVReadRAMDAC(dev, 0, reg2) : 0; | ||
224 | uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; | ||
225 | uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; | ||
226 | uint32_t oldramdac580 = 0, ramdac580 = 0; | ||
227 | bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */ | ||
228 | uint32_t saved_powerctrl_1 = 0, savedc040 = 0; | ||
229 | int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1); | ||
230 | |||
231 | /* model specific additions to generic pll1 and pll2 set up above */ | ||
232 | if (nv3035) { | ||
233 | pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 | | ||
234 | (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4; | ||
235 | pll2 = 0; | ||
236 | } | ||
237 | if (chip_version > 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { /* !nv40 */ | ||
238 | oldramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580); | ||
239 | ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); | ||
240 | if (oldramdac580 != ramdac580) | ||
241 | oldpll1 = ~0; /* force mismatch */ | ||
242 | if (single_stage) | ||
243 | /* magic value used by nvidia in single stage mode */ | ||
244 | pll2 |= 0x011f; | ||
245 | } | ||
246 | if (chip_version > 0x70) | ||
247 | /* magic bits set by the blob (but not the bios) on g71-73 */ | ||
248 | pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28; | ||
249 | |||
250 | if (oldpll1 == pll1 && oldpll2 == pll2) | ||
251 | return; /* already set */ | ||
252 | |||
253 | if (shift_powerctrl_1 >= 0) { | ||
254 | saved_powerctrl_1 = nvReadMC(dev, NV_PBUS_POWERCTRL_1); | ||
255 | nvWriteMC(dev, NV_PBUS_POWERCTRL_1, | ||
256 | (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | | ||
257 | 1 << shift_powerctrl_1); | ||
258 | } | ||
259 | |||
260 | if (chip_version >= 0x40) { | ||
261 | int shift_c040 = 14; | ||
262 | |||
263 | switch (reg1) { | ||
264 | case NV_PRAMDAC_MPLL_COEFF: | ||
265 | shift_c040 += 2; | ||
266 | case NV_PRAMDAC_NVPLL_COEFF: | ||
267 | shift_c040 += 2; | ||
268 | case NV_RAMDAC_VPLL2: | ||
269 | shift_c040 += 2; | ||
270 | case NV_PRAMDAC_VPLL_COEFF: | ||
271 | shift_c040 += 2; | ||
272 | } | ||
273 | |||
274 | savedc040 = nvReadMC(dev, 0xc040); | ||
275 | if (shift_c040 != 14) | ||
276 | nvWriteMC(dev, 0xc040, savedc040 & ~(3 << shift_c040)); | ||
277 | } | ||
278 | |||
279 | if (oldramdac580 != ramdac580) | ||
280 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_580, ramdac580); | ||
281 | |||
282 | if (!nv3035) | ||
283 | NVWriteRAMDAC(dev, 0, reg2, pll2); | ||
284 | NVWriteRAMDAC(dev, 0, reg1, pll1); | ||
285 | |||
286 | if (shift_powerctrl_1 >= 0) | ||
287 | nvWriteMC(dev, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); | ||
288 | if (chip_version >= 0x40) | ||
289 | nvWriteMC(dev, 0xc040, savedc040); | ||
290 | } | ||
291 | |||
292 | static void | ||
293 | setPLL_double_lowregs(struct drm_device *dev, uint32_t NMNMreg, | ||
294 | struct nouveau_pll_vals *pv) | ||
295 | { | ||
296 | /* When setting PLLs, there is a merry game of disabling and enabling | ||
297 | * various bits of hardware during the process. This function is a | ||
298 | * synthesis of six nv4x traces, nearly each card doing a subtly | ||
299 | * different thing. With luck all the necessary bits for each card are | ||
300 | * combined herein. Without luck it deviates from each card's formula | ||
301 | * so as to not work on any :) | ||
302 | */ | ||
303 | |||
304 | uint32_t Preg = NMNMreg - 4; | ||
305 | bool mpll = Preg == 0x4020; | ||
306 | uint32_t oldPval = nvReadMC(dev, Preg); | ||
307 | uint32_t NMNM = pv->NM2 << 16 | pv->NM1; | ||
308 | uint32_t Pval = (oldPval & (mpll ? ~(0x77 << 16) : ~(7 << 16))) | | ||
309 | 0xc << 28 | pv->log2P << 16; | ||
310 | uint32_t saved4600 = 0; | ||
311 | /* some cards have different maskc040s */ | ||
312 | uint32_t maskc040 = ~(3 << 14), savedc040; | ||
313 | bool single_stage = !pv->NM2 || pv->N2 == pv->M2; | ||
314 | |||
315 | if (nvReadMC(dev, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) | ||
316 | return; | ||
317 | |||
318 | if (Preg == 0x4000) | ||
319 | maskc040 = ~0x333; | ||
320 | if (Preg == 0x4058) | ||
321 | maskc040 = ~(0xc << 24); | ||
322 | |||
323 | if (mpll) { | ||
324 | struct pll_lims pll_lim; | ||
325 | uint8_t Pval2; | ||
326 | |||
327 | if (get_pll_limits(dev, Preg, &pll_lim)) | ||
328 | return; | ||
329 | |||
330 | Pval2 = pv->log2P + pll_lim.log2p_bias; | ||
331 | if (Pval2 > pll_lim.max_log2p) | ||
332 | Pval2 = pll_lim.max_log2p; | ||
333 | Pval |= 1 << 28 | Pval2 << 20; | ||
334 | |||
335 | saved4600 = nvReadMC(dev, 0x4600); | ||
336 | nvWriteMC(dev, 0x4600, saved4600 | 8 << 28); | ||
337 | } | ||
338 | if (single_stage) | ||
339 | Pval |= mpll ? 1 << 12 : 1 << 8; | ||
340 | |||
341 | nvWriteMC(dev, Preg, oldPval | 1 << 28); | ||
342 | nvWriteMC(dev, Preg, Pval & ~(4 << 28)); | ||
343 | if (mpll) { | ||
344 | Pval |= 8 << 20; | ||
345 | nvWriteMC(dev, 0x4020, Pval & ~(0xc << 28)); | ||
346 | nvWriteMC(dev, 0x4038, Pval & ~(0xc << 28)); | ||
347 | } | ||
348 | |||
349 | savedc040 = nvReadMC(dev, 0xc040); | ||
350 | nvWriteMC(dev, 0xc040, savedc040 & maskc040); | ||
351 | |||
352 | nvWriteMC(dev, NMNMreg, NMNM); | ||
353 | if (NMNMreg == 0x4024) | ||
354 | nvWriteMC(dev, 0x403c, NMNM); | ||
355 | |||
356 | nvWriteMC(dev, Preg, Pval); | ||
357 | if (mpll) { | ||
358 | Pval &= ~(8 << 20); | ||
359 | nvWriteMC(dev, 0x4020, Pval); | ||
360 | nvWriteMC(dev, 0x4038, Pval); | ||
361 | nvWriteMC(dev, 0x4600, saved4600); | ||
362 | } | ||
363 | |||
364 | nvWriteMC(dev, 0xc040, savedc040); | ||
365 | |||
366 | if (mpll) { | ||
367 | nvWriteMC(dev, 0x4020, Pval & ~(1 << 28)); | ||
368 | nvWriteMC(dev, 0x4038, Pval & ~(1 << 28)); | ||
369 | } | ||
370 | } | ||
371 | |||
372 | void | ||
373 | nouveau_hw_setpll(struct drm_device *dev, uint32_t reg1, | ||
374 | struct nouveau_pll_vals *pv) | ||
375 | { | ||
376 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
377 | int cv = dev_priv->vbios.chip_version; | ||
378 | |||
379 | if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || | ||
380 | cv >= 0x40) { | ||
381 | if (reg1 > 0x405c) | ||
382 | setPLL_double_highregs(dev, reg1, pv); | ||
383 | else | ||
384 | setPLL_double_lowregs(dev, reg1, pv); | ||
385 | } else | ||
386 | setPLL_single(dev, reg1, pv); | ||
387 | } | ||
388 | |||
389 | /* | ||
390 | * PLL getting | 128 | * PLL getting |
391 | */ | 129 | */ |
392 | 130 | ||
@@ -423,12 +161,12 @@ nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, | |||
423 | } | 161 | } |
424 | 162 | ||
425 | int | 163 | int |
426 | nouveau_hw_get_pllvals(struct drm_device *dev, enum pll_types plltype, | 164 | nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, |
427 | struct nouveau_pll_vals *pllvals) | 165 | struct nouveau_pll_vals *pllvals) |
428 | { | 166 | { |
429 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 167 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
430 | uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0; | 168 | uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0; |
431 | struct pll_lims pll_lim; | 169 | struct nvbios_pll pll_lim; |
432 | int ret; | 170 | int ret; |
433 | 171 | ||
434 | if (reg1 == 0) | 172 | if (reg1 == 0) |
@@ -478,7 +216,7 @@ nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pv) | |||
478 | } | 216 | } |
479 | 217 | ||
480 | int | 218 | int |
481 | nouveau_hw_get_clock(struct drm_device *dev, enum pll_types plltype) | 219 | nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype) |
482 | { | 220 | { |
483 | struct nouveau_pll_vals pllvals; | 221 | struct nouveau_pll_vals pllvals; |
484 | int ret; | 222 | int ret; |
@@ -517,9 +255,9 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | |||
517 | * when such a condition detected. only seen on nv11 to date | 255 | * when such a condition detected. only seen on nv11 to date |
518 | */ | 256 | */ |
519 | 257 | ||
520 | struct pll_lims pll_lim; | 258 | struct nvbios_pll pll_lim; |
521 | struct nouveau_pll_vals pv; | 259 | struct nouveau_pll_vals pv; |
522 | enum pll_types pll = head ? PLL_VPLL1 : PLL_VPLL0; | 260 | enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0; |
523 | 261 | ||
524 | if (get_pll_limits(dev, pll, &pll_lim)) | 262 | if (get_pll_limits(dev, pll, &pll_lim)) |
525 | return; | 263 | return; |
@@ -527,7 +265,7 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | |||
527 | 265 | ||
528 | if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && | 266 | if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && |
529 | pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && | 267 | pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && |
530 | pv.log2P <= pll_lim.max_log2p) | 268 | pv.log2P <= pll_lim.max_p) |
531 | return; | 269 | return; |
532 | 270 | ||
533 | NV_WARN(dev, "VPLL %d outwith limits, attempting to fix\n", head + 1); | 271 | NV_WARN(dev, "VPLL %d outwith limits, attempting to fix\n", head + 1); |
@@ -535,7 +273,7 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | |||
535 | /* set lowest clock within static limits */ | 273 | /* set lowest clock within static limits */ |
536 | pv.M1 = pll_lim.vco1.max_m; | 274 | pv.M1 = pll_lim.vco1.max_m; |
537 | pv.N1 = pll_lim.vco1.min_n; | 275 | pv.N1 = pll_lim.vco1.min_n; |
538 | pv.log2P = pll_lim.max_usable_log2p; | 276 | pv.log2P = pll_lim.max_p_usable; |
539 | nouveau_hw_setpll(dev, pll_lim.reg, &pv); | 277 | nouveau_hw_setpll(dev, pll_lim.reg, &pv); |
540 | } | 278 | } |
541 | 279 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/nouveau_hw.h index 2989090b9434..ff7f31c279d8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.h +++ b/drivers/gpu/drm/nouveau/nouveau_hw.h | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "drmP.h" | 26 | #include "drmP.h" |
27 | #include "nouveau_drv.h" | 27 | #include "nouveau_drv.h" |
28 | 28 | ||
29 | #include <subdev/bios/pll.h> | ||
30 | |||
29 | #define MASK(field) ( \ | 31 | #define MASK(field) ( \ |
30 | (0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field)) | 32 | (0xffffffff >> (31 - ((1 ? field) - (0 ? field)))) << (0 ? field)) |
31 | 33 | ||
@@ -38,12 +40,10 @@ void NVWriteVgaGr(struct drm_device *, int head, uint8_t index, uint8_t value); | |||
38 | uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index); | 40 | uint8_t NVReadVgaGr(struct drm_device *, int head, uint8_t index); |
39 | void NVSetOwner(struct drm_device *, int owner); | 41 | void NVSetOwner(struct drm_device *, int owner); |
40 | void NVBlankScreen(struct drm_device *, int head, bool blank); | 42 | void NVBlankScreen(struct drm_device *, int head, bool blank); |
41 | void nouveau_hw_setpll(struct drm_device *, uint32_t reg1, | 43 | int nouveau_hw_get_pllvals(struct drm_device *, enum nvbios_pll_type plltype, |
42 | struct nouveau_pll_vals *pv); | ||
43 | int nouveau_hw_get_pllvals(struct drm_device *, enum pll_types plltype, | ||
44 | struct nouveau_pll_vals *pllvals); | 44 | struct nouveau_pll_vals *pllvals); |
45 | int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals); | 45 | int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals); |
46 | int nouveau_hw_get_clock(struct drm_device *, enum pll_types plltype); | 46 | int nouveau_hw_get_clock(struct drm_device *, enum nvbios_pll_type plltype); |
47 | void nouveau_hw_save_vga_fonts(struct drm_device *, bool save); | 47 | void nouveau_hw_save_vga_fonts(struct drm_device *, bool save); |
48 | void nouveau_hw_save_state(struct drm_device *, int head, | 48 | void nouveau_hw_save_state(struct drm_device *, int head, |
49 | struct nv04_mode_state *state); | 49 | struct nv04_mode_state *state); |
@@ -55,8 +55,6 @@ void nouveau_hw_load_state_palette(struct drm_device *, int head, | |||
55 | /* nouveau_calc.c */ | 55 | /* nouveau_calc.c */ |
56 | extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, | 56 | extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, |
57 | int *burst, int *lwm); | 57 | int *burst, int *lwm); |
58 | extern int nouveau_calc_pll_mnp(struct drm_device *, struct pll_lims *pll_lim, | ||
59 | int clk, struct nouveau_pll_vals *pv); | ||
60 | 58 | ||
61 | static inline uint32_t | 59 | static inline uint32_t |
62 | nvReadMC(struct drm_device *dev, uint32_t reg) | 60 | nvReadMC(struct drm_device *dev, uint32_t reg) |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 43accc11102f..93ca09b90da5 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -108,7 +108,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod | |||
108 | struct nv04_mode_state *state = &dev_priv->mode_reg; | 108 | struct nv04_mode_state *state = &dev_priv->mode_reg; |
109 | struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; | 109 | struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; |
110 | struct nouveau_pll_vals *pv = ®p->pllvals; | 110 | struct nouveau_pll_vals *pv = ®p->pllvals; |
111 | struct pll_lims pll_lim; | 111 | struct nvbios_pll pll_lim; |
112 | 112 | ||
113 | if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim)) | 113 | if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim)) |
114 | return; | 114 | return; |
@@ -126,7 +126,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod | |||
126 | * has yet been observed in allowing the use a single stage pll on all | 126 | * has yet been observed in allowing the use a single stage pll on all |
127 | * nv43 however. the behaviour of single stage use is untested on nv40 | 127 | * nv43 however. the behaviour of single stage use is untested on nv40 |
128 | */ | 128 | */ |
129 | if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.maxfreq / 2)) | 129 | if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2)) |
130 | memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); | 130 | memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); |
131 | 131 | ||
132 | if (!nouveau_calc_pll_mnp(dev, &pll_lim, dot_clock, pv)) | 132 | if (!nouveau_calc_pll_mnp(dev, &pll_lim, dot_clock, pv)) |
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c index 6e7589918fa9..4528d48dc52b 100644 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/drivers/gpu/drm/nouveau/nv04_pm.c | |||
@@ -46,7 +46,7 @@ nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | |||
46 | } | 46 | } |
47 | 47 | ||
48 | struct nv04_pm_clock { | 48 | struct nv04_pm_clock { |
49 | struct pll_lims pll; | 49 | struct nvbios_pll pll; |
50 | struct nouveau_pll_vals calc; | 50 | struct nouveau_pll_vals calc; |
51 | }; | 51 | }; |
52 | 52 | ||
diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index 661d9cfd980d..d857525666ee 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c | |||
@@ -107,7 +107,7 @@ struct nv40_pm_state { | |||
107 | }; | 107 | }; |
108 | 108 | ||
109 | static int | 109 | static int |
110 | nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, | 110 | nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, |
111 | u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) | 111 | u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) |
112 | { | 112 | { |
113 | struct nouveau_pll_vals coef; | 113 | struct nouveau_pll_vals coef; |
@@ -117,8 +117,8 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, | |||
117 | if (ret) | 117 | if (ret) |
118 | return ret; | 118 | return ret; |
119 | 119 | ||
120 | if (clk < pll->vco1.maxfreq) | 120 | if (clk < pll->vco1.max_freq) |
121 | pll->vco2.maxfreq = 0; | 121 | pll->vco2.max_freq = 0; |
122 | 122 | ||
123 | ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); | 123 | ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); |
124 | if (ret == 0) | 124 | if (ret == 0) |
@@ -127,7 +127,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, | |||
127 | *N1 = coef.N1; | 127 | *N1 = coef.N1; |
128 | *M1 = coef.M1; | 128 | *M1 = coef.M1; |
129 | if (N2 && M2) { | 129 | if (N2 && M2) { |
130 | if (pll->vco2.maxfreq) { | 130 | if (pll->vco2.max_freq) { |
131 | *N2 = coef.N2; | 131 | *N2 = coef.N2; |
132 | *M2 = coef.M2; | 132 | *M2 = coef.M2; |
133 | } else { | 133 | } else { |
@@ -143,7 +143,7 @@ void * | |||
143 | nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | 143 | nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) |
144 | { | 144 | { |
145 | struct nv40_pm_state *info; | 145 | struct nv40_pm_state *info; |
146 | struct pll_lims pll; | 146 | struct nvbios_pll pll; |
147 | int N1, N2, M1, M2, log2P; | 147 | int N1, N2, M1, M2, log2P; |
148 | int ret; | 148 | int ret; |
149 | 149 | ||
@@ -191,7 +191,7 @@ nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | |||
191 | goto out; | 191 | goto out; |
192 | 192 | ||
193 | info->mpll_ctrl = 0x80000000 | (log2P << 16); | 193 | info->mpll_ctrl = 0x80000000 | (log2P << 16); |
194 | info->mpll_ctrl |= min2(pll.log2p_bias + log2P, pll.max_log2p) << 20; | 194 | info->mpll_ctrl |= min2(pll.bias_p + log2P, pll.max_p) << 20; |
195 | if (N2 == M2) { | 195 | if (N2 == M2) { |
196 | info->mpll_ctrl |= 0x00000100; | 196 | info->mpll_ctrl |= 0x00000100; |
197 | info->mpll_coef = (N1 << 8) | M1; | 197 | info->mpll_coef = (N1 << 8) | M1; |
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 22cebd5dd694..40042c1bbc6e 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -329,55 +329,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) | |||
329 | int | 329 | int |
330 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | 330 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) |
331 | { | 331 | { |
332 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 332 | return setPLL(dev, PLL_VPLL0 + head, pclk); |
333 | struct pll_lims pll; | ||
334 | uint32_t reg1, reg2; | ||
335 | int ret, N1, M1, N2, M2, P; | ||
336 | |||
337 | ret = get_pll_limits(dev, PLL_VPLL0 + head, &pll); | ||
338 | if (ret) | ||
339 | return ret; | ||
340 | |||
341 | if (pll.vco2.maxfreq) { | ||
342 | ret = nv50_calc_pll(dev, &pll, pclk, &N1, &M1, &N2, &M2, &P); | ||
343 | if (ret <= 0) | ||
344 | return 0; | ||
345 | |||
346 | NV_DEBUG(dev, "pclk %d out %d NM1 %d %d NM2 %d %d P %d\n", | ||
347 | pclk, ret, N1, M1, N2, M2, P); | ||
348 | |||
349 | reg1 = nv_rd32(dev, pll.reg + 4) & 0xff00ff00; | ||
350 | reg2 = nv_rd32(dev, pll.reg + 8) & 0x8000ff00; | ||
351 | nv_wr32(dev, pll.reg + 0, 0x10000611); | ||
352 | nv_wr32(dev, pll.reg + 4, reg1 | (M1 << 16) | N1); | ||
353 | nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); | ||
354 | } else | ||
355 | if (dev_priv->chipset < NV_C0) { | ||
356 | ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); | ||
357 | if (ret <= 0) | ||
358 | return 0; | ||
359 | |||
360 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", | ||
361 | pclk, ret, N1, N2, M1, P); | ||
362 | |||
363 | reg1 = nv_rd32(dev, pll.reg + 4) & 0xffc00000; | ||
364 | nv_wr32(dev, pll.reg + 0, 0x50000610); | ||
365 | nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); | ||
366 | nv_wr32(dev, pll.reg + 8, N2); | ||
367 | } else { | ||
368 | ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); | ||
369 | if (ret <= 0) | ||
370 | return 0; | ||
371 | |||
372 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", | ||
373 | pclk, ret, N1, N2, M1, P); | ||
374 | |||
375 | nv_mask(dev, pll.reg + 0x0c, 0x00000000, 0x00000100); | ||
376 | nv_wr32(dev, pll.reg + 0x04, (P << 16) | (N1 << 8) | M1); | ||
377 | nv_wr32(dev, pll.reg + 0x10, N2 << 16); | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | 333 | } |
382 | 334 | ||
383 | static void | 335 | static void |
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index be5704fd4a86..378ca8ca9d6a 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c | |||
@@ -363,7 +363,7 @@ struct nv50_pm_state { | |||
363 | }; | 363 | }; |
364 | 364 | ||
365 | static u32 | 365 | static u32 |
366 | calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, | 366 | calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, |
367 | u32 clk, int *N1, int *M1, int *log2P) | 367 | u32 clk, int *N1, int *M1, int *log2P) |
368 | { | 368 | { |
369 | struct nouveau_pll_vals coef; | 369 | struct nouveau_pll_vals coef; |
@@ -373,7 +373,7 @@ calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, | |||
373 | if (ret) | 373 | if (ret) |
374 | return 0; | 374 | return 0; |
375 | 375 | ||
376 | pll->vco2.maxfreq = 0; | 376 | pll->vco2.max_freq = 0; |
377 | pll->refclk = read_pll_ref(dev, reg); | 377 | pll->refclk = read_pll_ref(dev, reg); |
378 | if (!pll->refclk) | 378 | if (!pll->refclk) |
379 | return 0; | 379 | return 0; |
@@ -542,7 +542,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | |||
542 | .priv = info | 542 | .priv = info |
543 | }; | 543 | }; |
544 | struct hwsq_ucode *hwsq = &info->mclk_hwsq; | 544 | struct hwsq_ucode *hwsq = &info->mclk_hwsq; |
545 | struct pll_lims pll; | 545 | struct nvbios_pll pll; |
546 | int N, M, P; | 546 | int N, M, P; |
547 | int ret; | 547 | int ret; |
548 | 548 | ||
@@ -550,14 +550,14 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | |||
550 | info->mctrl = nv_rd32(dev, 0x004008); | 550 | info->mctrl = nv_rd32(dev, 0x004008); |
551 | info->mctrl &= ~0x81ff0200; | 551 | info->mctrl &= ~0x81ff0200; |
552 | if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { | 552 | if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { |
553 | info->mctrl |= 0x00000200 | (pll.log2p_bias << 19); | 553 | info->mctrl |= 0x00000200 | (pll.bias_p << 19); |
554 | } else { | 554 | } else { |
555 | ret = calc_pll(dev, 0x4008, &pll, perflvl->memory, &N, &M, &P); | 555 | ret = calc_pll(dev, 0x4008, &pll, perflvl->memory, &N, &M, &P); |
556 | if (ret == 0) | 556 | if (ret == 0) |
557 | return -EINVAL; | 557 | return -EINVAL; |
558 | 558 | ||
559 | info->mctrl |= 0x80000000 | (P << 22) | (P << 16); | 559 | info->mctrl |= 0x80000000 | (P << 22) | (P << 16); |
560 | info->mctrl |= pll.log2p_bias << 19; | 560 | info->mctrl |= pll.bias_p << 19; |
561 | info->mcoef = (N << 8) | M; | 561 | info->mcoef = (N << 8) | M; |
562 | } | 562 | } |
563 | 563 | ||
@@ -590,7 +590,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | |||
590 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 590 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
591 | struct nv50_pm_state *info; | 591 | struct nv50_pm_state *info; |
592 | struct hwsq_ucode *hwsq; | 592 | struct hwsq_ucode *hwsq; |
593 | struct pll_lims pll; | 593 | struct nvbios_pll pll; |
594 | u32 out, mast, divs, ctrl; | 594 | u32 out, mast, divs, ctrl; |
595 | int clk, ret = -EINVAL; | 595 | int clk, ret = -EINVAL; |
596 | int N, M, P1, P2; | 596 | int N, M, P1, P2; |
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index ff0fafbfe621..847c616de12f 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c | |||
@@ -111,7 +111,7 @@ struct creg { | |||
111 | static int | 111 | static int |
112 | calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) | 112 | calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) |
113 | { | 113 | { |
114 | struct pll_lims limits; | 114 | struct nvbios_pll limits; |
115 | u32 oclk, sclk, sdiv; | 115 | u32 oclk, sclk, sdiv; |
116 | int P, N, M, diff; | 116 | int P, N, M, diff; |
117 | int ret; | 117 | int ret; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 81b649864fa1..4a21a7264c3c 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c | |||
@@ -212,7 +212,7 @@ calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv) | |||
212 | static u32 | 212 | static u32 |
213 | calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) | 213 | calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) |
214 | { | 214 | { |
215 | struct pll_lims limits; | 215 | struct nvbios_pll limits; |
216 | int N, M, P, ret; | 216 | int N, M, P, ret; |
217 | 217 | ||
218 | ret = get_pll_limits(dev, 0x137000 + (clk * 0x20), &limits); | 218 | ret = get_pll_limits(dev, 0x137000 + (clk * 0x20), &limits); |
@@ -308,7 +308,7 @@ calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) | |||
308 | static int | 308 | static int |
309 | calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) | 309 | calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) |
310 | { | 310 | { |
311 | struct pll_lims pll; | 311 | struct nvbios_pll pll; |
312 | int N, M, P, ret; | 312 | int N, M, P, ret; |
313 | u32 ctrl; | 313 | u32 ctrl; |
314 | 314 | ||