1 | /* $NetBSD: nouveau_subdev_bios_pll.c,v 1.2 2015/02/25 17:29:43 riastradh Exp $ */ |
2 | |
3 | /* |
4 | * Copyright 2005-2006 Erik Waling |
5 | * Copyright 2006 Stephane Marchesin |
6 | * Copyright 2007-2009 Stuart Bennett |
7 | * |
8 | * Permission is hereby granted, free of charge, to any person obtaining a |
9 | * copy of this software and associated documentation files (the "Software"), |
10 | * to deal in the Software without restriction, including without limitation |
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
12 | * and/or sell copies of the Software, and to permit persons to whom the |
13 | * Software is furnished to do so, subject to the following conditions: |
14 | * |
15 | * The above copyright notice and this permission notice shall be included in |
16 | * all copies or substantial portions of the Software. |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
21 | * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF |
23 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
24 | * SOFTWARE. |
25 | */ |
26 | |
27 | #include <sys/cdefs.h> |
28 | __KERNEL_RCSID(0, "$NetBSD: nouveau_subdev_bios_pll.c,v 1.2 2015/02/25 17:29:43 riastradh Exp $" ); |
29 | |
30 | #include <subdev/vga.h> |
31 | #include <subdev/bios.h> |
32 | #include <subdev/bios/bit.h> |
33 | #include <subdev/bios/bmp.h> |
34 | #include <subdev/bios/pll.h> |
35 | |
36 | struct pll_mapping { |
37 | u8 type; |
38 | u32 reg; |
39 | }; |
40 | |
41 | static struct pll_mapping |
42 | nv04_pll_mapping[] = { |
43 | { PLL_CORE , 0x680500 }, |
44 | { PLL_MEMORY, 0x680504 }, |
45 | { PLL_VPLL0 , 0x680508 }, |
46 | { PLL_VPLL1 , 0x680520 }, |
47 | { } |
48 | }; |
49 | |
50 | static struct pll_mapping |
51 | nv40_pll_mapping[] = { |
52 | { PLL_CORE , 0x004000 }, |
53 | { PLL_MEMORY, 0x004020 }, |
54 | { PLL_VPLL0 , 0x680508 }, |
55 | { PLL_VPLL1 , 0x680520 }, |
56 | { } |
57 | }; |
58 | |
59 | static struct pll_mapping |
60 | nv50_pll_mapping[] = { |
61 | { PLL_CORE , 0x004028 }, |
62 | { PLL_SHADER, 0x004020 }, |
63 | { PLL_UNK03 , 0x004000 }, |
64 | { PLL_MEMORY, 0x004008 }, |
65 | { PLL_UNK40 , 0x00e810 }, |
66 | { PLL_UNK41 , 0x00e818 }, |
67 | { PLL_UNK42 , 0x00e824 }, |
68 | { PLL_VPLL0 , 0x614100 }, |
69 | { PLL_VPLL1 , 0x614900 }, |
70 | { } |
71 | }; |
72 | |
73 | static struct pll_mapping |
74 | nv84_pll_mapping[] = { |
75 | { PLL_CORE , 0x004028 }, |
76 | { PLL_SHADER, 0x004020 }, |
77 | { PLL_MEMORY, 0x004008 }, |
78 | { PLL_VDEC , 0x004030 }, |
79 | { PLL_UNK41 , 0x00e818 }, |
80 | { PLL_VPLL0 , 0x614100 }, |
81 | { PLL_VPLL1 , 0x614900 }, |
82 | { } |
83 | }; |
84 | |
85 | static u16 |
86 | pll_limits_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) |
87 | { |
88 | struct bit_entry bit_C; |
89 | |
90 | if (!bit_entry(bios, 'C', &bit_C) && bit_C.length >= 10) { |
91 | u16 data = nv_ro16(bios, bit_C.offset + 8); |
92 | if (data) { |
93 | *ver = nv_ro08(bios, data + 0); |
94 | *hdr = nv_ro08(bios, data + 1); |
95 | *len = nv_ro08(bios, data + 2); |
96 | *cnt = nv_ro08(bios, data + 3); |
97 | return data; |
98 | } |
99 | } |
100 | |
101 | if (bmp_version(bios) >= 0x0524) { |
102 | u16 data = nv_ro16(bios, bios->bmp_offset + 142); |
103 | if (data) { |
104 | *ver = nv_ro08(bios, data + 0); |
105 | *hdr = 1; |
106 | *cnt = 1; |
107 | *len = 0x18; |
108 | return data; |
109 | } |
110 | } |
111 | |
112 | *ver = 0x00; |
113 | return 0x0000; |
114 | } |
115 | |
116 | static struct pll_mapping * |
117 | pll_map(struct nouveau_bios *bios) |
118 | { |
119 | switch (nv_device(bios)->card_type) { |
120 | case NV_04: |
121 | case NV_10: |
122 | case NV_11: |
123 | case NV_20: |
124 | case NV_30: |
125 | return nv04_pll_mapping; |
126 | break; |
127 | case NV_40: |
128 | return nv40_pll_mapping; |
129 | case NV_50: |
130 | if (nv_device(bios)->chipset == 0x50) |
131 | return nv50_pll_mapping; |
132 | else |
133 | if (nv_device(bios)->chipset < 0xa3 || |
134 | nv_device(bios)->chipset == 0xaa || |
135 | nv_device(bios)->chipset == 0xac) |
136 | return nv84_pll_mapping; |
137 | default: |
138 | return NULL; |
139 | } |
140 | } |
141 | |
142 | static u16 |
143 | pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) |
144 | { |
145 | struct pll_mapping *map; |
146 | u8 hdr, cnt; |
147 | u16 data; |
148 | |
149 | data = pll_limits_table(bios, ver, &hdr, &cnt, len); |
150 | if (data && *ver >= 0x30) { |
151 | data += hdr; |
152 | while (cnt--) { |
153 | if (nv_ro32(bios, data + 3) == reg) { |
154 | *type = nv_ro08(bios, data + 0); |
155 | return data; |
156 | } |
157 | data += *len; |
158 | } |
159 | return 0x0000; |
160 | } |
161 | |
162 | map = pll_map(bios); |
163 | while (map->reg) { |
164 | if (map->reg == reg && *ver >= 0x20) { |
165 | u16 addr = (data += hdr); |
166 | *type = map->type; |
167 | while (cnt--) { |
168 | if (nv_ro32(bios, data) == map->reg) |
169 | return data; |
170 | data += *len; |
171 | } |
172 | return addr; |
173 | } else |
174 | if (map->reg == reg) { |
175 | *type = map->type; |
176 | return data + 1; |
177 | } |
178 | map++; |
179 | } |
180 | |
181 | return 0x0000; |
182 | } |
183 | |
184 | static u16 |
185 | pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) |
186 | { |
187 | struct pll_mapping *map; |
188 | u8 hdr, cnt; |
189 | u16 data; |
190 | |
191 | data = pll_limits_table(bios, ver, &hdr, &cnt, len); |
192 | if (data && *ver >= 0x30) { |
193 | data += hdr; |
194 | while (cnt--) { |
195 | if (nv_ro08(bios, data + 0) == type) { |
196 | *reg = nv_ro32(bios, data + 3); |
197 | return data; |
198 | } |
199 | data += *len; |
200 | } |
201 | return 0x0000; |
202 | } |
203 | |
204 | map = pll_map(bios); |
205 | while (map->reg) { |
206 | if (map->type == type && *ver >= 0x20) { |
207 | u16 addr = (data += hdr); |
208 | *reg = map->reg; |
209 | while (cnt--) { |
210 | if (nv_ro32(bios, data) == map->reg) |
211 | return data; |
212 | data += *len; |
213 | } |
214 | return addr; |
215 | } else |
216 | if (map->type == type) { |
217 | *reg = map->reg; |
218 | return data + 1; |
219 | } |
220 | map++; |
221 | } |
222 | |
223 | return 0x0000; |
224 | } |
225 | |
226 | int |
227 | nvbios_pll_parse(struct nouveau_bios *bios, u32 type, struct nvbios_pll *info) |
228 | { |
229 | u8 ver, len; |
230 | u32 reg = type; |
231 | u16 data; |
232 | |
233 | if (type > PLL_MAX) { |
234 | reg = type; |
235 | data = pll_map_reg(bios, reg, &type, &ver, &len); |
236 | } else { |
237 | data = pll_map_type(bios, type, ®, &ver, &len); |
238 | } |
239 | |
240 | if (ver && !data) |
241 | return -ENOENT; |
242 | |
243 | memset(info, 0, sizeof(*info)); |
244 | info->type = type; |
245 | info->reg = reg; |
246 | |
247 | switch (ver) { |
248 | case 0x00: |
249 | break; |
250 | case 0x10: |
251 | case 0x11: |
252 | info->vco1.min_freq = nv_ro32(bios, data + 0); |
253 | info->vco1.max_freq = nv_ro32(bios, data + 4); |
254 | info->vco2.min_freq = nv_ro32(bios, data + 8); |
255 | info->vco2.max_freq = nv_ro32(bios, data + 12); |
256 | info->vco1.min_inputfreq = nv_ro32(bios, data + 16); |
257 | info->vco2.min_inputfreq = nv_ro32(bios, data + 20); |
258 | info->vco1.max_inputfreq = INT_MAX; |
259 | info->vco2.max_inputfreq = INT_MAX; |
260 | |
261 | info->max_p = 0x7; |
262 | info->max_p_usable = 0x6; |
263 | |
264 | /* these values taken from nv30/31/36 */ |
265 | switch (bios->version.chip) { |
266 | case 0x36: |
267 | info->vco1.min_n = 0x5; |
268 | break; |
269 | default: |
270 | info->vco1.min_n = 0x1; |
271 | break; |
272 | } |
273 | info->vco1.max_n = 0xff; |
274 | info->vco1.min_m = 0x1; |
275 | info->vco1.max_m = 0xd; |
276 | |
277 | /* |
278 | * On nv30, 31, 36 (i.e. all cards with two stage PLLs with this |
279 | * table version (apart from nv35)), N2 is compared to |
280 | * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and |
281 | * save a comparison |
282 | */ |
283 | info->vco2.min_n = 0x4; |
284 | switch (bios->version.chip) { |
285 | case 0x30: |
286 | case 0x35: |
287 | info->vco2.max_n = 0x1f; |
288 | break; |
289 | default: |
290 | info->vco2.max_n = 0x28; |
291 | break; |
292 | } |
293 | info->vco2.min_m = 0x1; |
294 | info->vco2.max_m = 0x4; |
295 | break; |
296 | case 0x20: |
297 | case 0x21: |
298 | info->vco1.min_freq = nv_ro16(bios, data + 4) * 1000; |
299 | info->vco1.max_freq = nv_ro16(bios, data + 6) * 1000; |
300 | info->vco2.min_freq = nv_ro16(bios, data + 8) * 1000; |
301 | info->vco2.max_freq = nv_ro16(bios, data + 10) * 1000; |
302 | info->vco1.min_inputfreq = nv_ro16(bios, data + 12) * 1000; |
303 | info->vco2.min_inputfreq = nv_ro16(bios, data + 14) * 1000; |
304 | info->vco1.max_inputfreq = nv_ro16(bios, data + 16) * 1000; |
305 | info->vco2.max_inputfreq = nv_ro16(bios, data + 18) * 1000; |
306 | info->vco1.min_n = nv_ro08(bios, data + 20); |
307 | info->vco1.max_n = nv_ro08(bios, data + 21); |
308 | info->vco1.min_m = nv_ro08(bios, data + 22); |
309 | info->vco1.max_m = nv_ro08(bios, data + 23); |
310 | info->vco2.min_n = nv_ro08(bios, data + 24); |
311 | info->vco2.max_n = nv_ro08(bios, data + 25); |
312 | info->vco2.min_m = nv_ro08(bios, data + 26); |
313 | info->vco2.max_m = nv_ro08(bios, data + 27); |
314 | |
315 | info->max_p = nv_ro08(bios, data + 29); |
316 | info->max_p_usable = info->max_p; |
317 | if (bios->version.chip < 0x60) |
318 | info->max_p_usable = 0x6; |
319 | info->bias_p = nv_ro08(bios, data + 30); |
320 | |
321 | if (len > 0x22) |
322 | info->refclk = nv_ro32(bios, data + 31); |
323 | break; |
324 | case 0x30: |
325 | data = nv_ro16(bios, data + 1); |
326 | |
327 | info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; |
328 | info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; |
329 | info->vco2.min_freq = nv_ro16(bios, data + 4) * 1000; |
330 | info->vco2.max_freq = nv_ro16(bios, data + 6) * 1000; |
331 | info->vco1.min_inputfreq = nv_ro16(bios, data + 8) * 1000; |
332 | info->vco2.min_inputfreq = nv_ro16(bios, data + 10) * 1000; |
333 | info->vco1.max_inputfreq = nv_ro16(bios, data + 12) * 1000; |
334 | info->vco2.max_inputfreq = nv_ro16(bios, data + 14) * 1000; |
335 | info->vco1.min_n = nv_ro08(bios, data + 16); |
336 | info->vco1.max_n = nv_ro08(bios, data + 17); |
337 | info->vco1.min_m = nv_ro08(bios, data + 18); |
338 | info->vco1.max_m = nv_ro08(bios, data + 19); |
339 | info->vco2.min_n = nv_ro08(bios, data + 20); |
340 | info->vco2.max_n = nv_ro08(bios, data + 21); |
341 | info->vco2.min_m = nv_ro08(bios, data + 22); |
342 | info->vco2.max_m = nv_ro08(bios, data + 23); |
343 | info->max_p_usable = info->max_p = nv_ro08(bios, data + 25); |
344 | info->bias_p = nv_ro08(bios, data + 27); |
345 | info->refclk = nv_ro32(bios, data + 28); |
346 | break; |
347 | case 0x40: |
348 | info->refclk = nv_ro16(bios, data + 9) * 1000; |
349 | data = nv_ro16(bios, data + 1); |
350 | |
351 | info->vco1.min_freq = nv_ro16(bios, data + 0) * 1000; |
352 | info->vco1.max_freq = nv_ro16(bios, data + 2) * 1000; |
353 | info->vco1.min_inputfreq = nv_ro16(bios, data + 4) * 1000; |
354 | info->vco1.max_inputfreq = nv_ro16(bios, data + 6) * 1000; |
355 | info->vco1.min_m = nv_ro08(bios, data + 8); |
356 | info->vco1.max_m = nv_ro08(bios, data + 9); |
357 | info->vco1.min_n = nv_ro08(bios, data + 10); |
358 | info->vco1.max_n = nv_ro08(bios, data + 11); |
359 | info->min_p = nv_ro08(bios, data + 12); |
360 | info->max_p = nv_ro08(bios, data + 13); |
361 | break; |
362 | default: |
363 | nv_error(bios, "unknown pll limits version 0x%02x\n" , ver); |
364 | return -EINVAL; |
365 | } |
366 | |
367 | if (!info->refclk) { |
368 | info->refclk = nv_device(bios)->crystal; |
369 | if (bios->version.chip == 0x51) { |
370 | u32 sel_clk = nv_rd32(bios, 0x680524); |
371 | if ((info->reg == 0x680508 && sel_clk & 0x20) || |
372 | (info->reg == 0x680520 && sel_clk & 0x80)) { |
373 | if (nv_rdvgac(bios, 0, 0x27) < 0xa3) |
374 | info->refclk = 200000; |
375 | else |
376 | info->refclk = 25000; |
377 | } |
378 | } |
379 | } |
380 | |
381 | /* |
382 | * By now any valid limit table ought to have set a max frequency for |
383 | * vco1, so if it's zero it's either a pre limit table bios, or one |
384 | * with an empty limit table (seen on nv18) |
385 | */ |
386 | if (!info->vco1.max_freq) { |
387 | info->vco1.max_freq = nv_ro32(bios, bios->bmp_offset + 67); |
388 | info->vco1.min_freq = nv_ro32(bios, bios->bmp_offset + 71); |
389 | if (bmp_version(bios) < 0x0506) { |
390 | info->vco1.max_freq = 256000; |
391 | info->vco1.min_freq = 128000; |
392 | } |
393 | |
394 | info->vco1.min_inputfreq = 0; |
395 | info->vco1.max_inputfreq = INT_MAX; |
396 | info->vco1.min_n = 0x1; |
397 | info->vco1.max_n = 0xff; |
398 | info->vco1.min_m = 0x1; |
399 | |
400 | if (nv_device(bios)->crystal == 13500) { |
401 | /* nv05 does this, nv11 doesn't, nv10 unknown */ |
402 | if (bios->version.chip < 0x11) |
403 | info->vco1.min_m = 0x7; |
404 | info->vco1.max_m = 0xd; |
405 | } else { |
406 | if (bios->version.chip < 0x11) |
407 | info->vco1.min_m = 0x8; |
408 | info->vco1.max_m = 0xe; |
409 | } |
410 | |
411 | if (bios->version.chip < 0x17 || |
412 | bios->version.chip == 0x1a || |
413 | bios->version.chip == 0x20) |
414 | info->max_p = 4; |
415 | else |
416 | info->max_p = 5; |
417 | info->max_p_usable = info->max_p; |
418 | } |
419 | |
420 | return 0; |
421 | } |
422 | |