1 /* program the DAC */
2 /* Authors:
3 Mark Watson 2/2000,
4 Apsed 2002,
5 Rudolf Cornelissen 9/2002-4/2003
6 */
7
8 #define MODULE_BIT 0x00010000
9
10 #include "mga_std.h"
11
12 static status_t milx_dac_pix_pll_find(
13 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
14 static status_t g100_g400max_dac_pix_pll_find(
15 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test);
16 static status_t g450_g550_dac_pix_pll_find(
17 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test);
18 static status_t g100_g400max_dac_sys_pll_find(
19 float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
20 static status_t g450_g550_dac_sys_pll_find(
21 float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
22
23 /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/
gx00_dac_mode(int mode,float brightness)24 status_t gx00_dac_mode(int mode,float brightness)
25 {
26 uint8 *r,*g,*b,t[64];
27 int i;
28
29 /*set colour arrays to point to space reserved in shared info*/
30 r=si->color_data;
31 g=r+256;
32 b=g+256;
33
34 LOG(4,("DAC: Setting screen mode %d brightness %f\n", mode, brightness));
35 /*init a basic palette for brightness specified*/
36 for (i=0;i<256;i++)
37 {
38 int ri = i*brightness; // apsed
39 if (ri > 255) ri = 255;
40 r[i]=ri;
41 }
42
43 /*modify the palette for the specified mode (&validate mode)*/
44 switch(mode)
45 {
46 case BPP8:
47 case BPP24:case BPP32:
48 for (i=0;i<256;i++)
49 {
50 b[i]=g[i]=r[i];
51 }
52 break;
53 case BPP16:
54 for (i=0;i<64;i++)
55 {
56 t[i]=r[i<<2];
57 }
58 for (i=0;i<64;i++)
59 {
60 g[i]=t[i];
61 }
62 for (i=0;i<32;i++)
63 {
64 b[i]=r[i]=t[i<<1];
65 }
66 break;
67 case BPP15:
68 for (i=0;i<32;i++)
69 {
70 t[i]=r[i<<3];
71 }
72 for (i=0;i<32;i++)
73 {
74 g[i]=r[i]=b[i]=t[i];
75 }
76 break;
77 case BPP32DIR:
78 break;
79 default:
80 LOG(8,("DAC: Invalid bit depth requested\n"));
81 return B_ERROR;
82 break;
83 }
84
85 if (gx00_dac_palette(r,g,b)!=B_OK) return B_ERROR;
86
87 /*set the mode - also sets VCLK dividor*/
88 if (si->ps.card_type >= G100)
89 {
90 DXIW(MULCTRL, mode);
91 LOG(2,("DAC: mulctrl 0x%02x\n", DXIR(MULCTRL)));
92 }
93 else
94 {
95 /* MIL1/2 differs here (TVP3026DAC) */
96 uint8 miscctrl = 0, latchctrl = 0;
97 uint8 tcolctrl = 0, mulctrl = 0;
98
99 /* set the mode */
100 switch (mode)
101 {
102 /* presetting mulctrl for DAC pixelbus_width of 32 */
103 case BPP8:
104 miscctrl=0x00; latchctrl=0x06; tcolctrl=0x80; mulctrl=0x4b;
105 break;
106 case BPP15:
107 miscctrl=0x20; latchctrl=0x06; tcolctrl=0x04; mulctrl=0x53;
108 break;
109 case BPP16:
110 miscctrl=0x20; latchctrl=0x06; tcolctrl=0x05; mulctrl=0x53;
111 break;
112 case BPP24:
113 miscctrl=0x20; latchctrl=0x06; tcolctrl=0x1f; mulctrl=0x5b;
114 break;
115 case BPP32:
116 miscctrl=0x20; latchctrl=0x07; tcolctrl=0x06; mulctrl=0x5b;
117 break;
118 case BPP32DIR:
119 miscctrl=0x20; latchctrl=0x07; tcolctrl=0x06; mulctrl=0x5b;
120 break;
121 }
122
123 /* modify mulctrl if DAC pixelbus_width is 64 */
124 //fixme? do 32bit DACbus MIL 1/2 cards exist? if so, setup via si->ps...
125 if (true) mulctrl += 1;
126
127 DXIW(MISCCTRL, (DXIR(MISCCTRL) & 0x1d) | miscctrl);
128 DXIW(TVP_LATCHCTRL, latchctrl);
129 DXIW(TVP_TCOLCTRL, tcolctrl);
130 DXIW(MULCTRL, mulctrl);
131
132 LOG(2,("DAC: TVP miscctrl 0x%02x, TVP latchctrl 0x%02x\n",
133 DXIR(MISCCTRL), DXIR(TVP_LATCHCTRL)));
134 LOG(2,("DAC: TVP tcolctrl 0x%02x, TVP mulctrl 0x%02x\n",
135 DXIR(TVP_TCOLCTRL), DXIR(MULCTRL)));
136 }
137
138 /* disable palette RAM adressing mask */
139 DACW(PIXRDMSK,0xff);
140 LOG(2,("DAC: pixrdmsk 0x%02x\n", DACR(PIXRDMSK)));
141
142 return B_OK;
143 }
144
145 /*program the DAC palette using the given r,g,b values*/
gx00_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256])146 status_t gx00_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256])
147 {
148 int i;
149
150 LOG(4,("DAC: setting palette\n"));
151
152 /* clear palwtadd before starting programming (LUT index) */
153 DACW(PALWTADD,0);
154
155 /*loop through all 256 to program DAC*/
156 for (i=0;i<256;i++)
157 {
158 DACW(PALDATA,r[i]);
159 DACW(PALDATA,g[i]);
160 DACW(PALDATA,b[i]);
161 }
162 if (DACR(PALWTADD)!=0)
163 {
164 LOG(8,("DAC: PALWTADD is not 0 after programming\n"));
165 return B_ERROR;
166 }
167 if (0)
168 {// apsed: reread LUT
169 uint8 R, G, B;
170
171 /* clear LUT color (modulo 3 counter) */
172 DACW(PALRDADD,0);
173 for (i=0;i<256;i++)
174 {
175 R = DACR(PALDATA);
176 G = DACR(PALDATA);
177 B = DACR(PALDATA);
178 if ((r[i] != R) || (g[i] != G) || (b[i] != B))
179 LOG(1,("DAC palette %d: w %x %x %x, r %x %x %x\n", i, r[i], g[i], b[i], R, G, B)); // apsed
180 }
181 }
182
183 return B_OK;
184 }
185
186 /*program the pixpll - frequency in kHz*/
187 /*important notes:
188 * MISC(clksel) = select A,B,C PIXPLL (25,28,none)
189 * PIXPLLC is used - others should be kept as is
190 * VCLK is quadword clock (max is PIXPLL/2) - set according to DEPTH
191 * BESCLK,CRTC2 are not touched
192 */
gx00_dac_set_pix_pll(display_mode target)193 status_t gx00_dac_set_pix_pll(display_mode target)
194 {
195 uint8 m=0,n=0,p=0;
196 uint time = 0;
197
198 float pix_setting, req_pclk;
199 status_t result;
200
201 req_pclk = (target.timing.pixel_clock)/1000.0;
202 LOG(4,("DAC: Setting PIX PLL for pixelclock %f\n", req_pclk));
203
204 /* signal that we actually want to set the mode */
205 result = gx00_dac_pix_pll_find(target,&pix_setting,&m,&n,&p, 1);
206 if (result != B_OK)
207 {
208 return result;
209 }
210
211 /*reprogram (disable,select,wait for stability,enable)*/
212 DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/
213 DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/
214 VGAW(MISCW,((VGAR(MISCR)&0xF3)|0x8)); /*select PIXPLLC*/
215 DXIW(PIXPLLCM,(m)); /*set m value*/
216 DXIW(PIXPLLCN,(n)); /*set n value*/
217 DXIW(PIXPLLCP,(p)); /*set p value*/
218
219 /* Wait for the PIXPLL frequency to lock until timeout occurs */
220 while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 2000))
221 {
222 time++;
223 snooze(1);
224 }
225
226 if (time > 2000)
227 LOG(2,("DAC: PIX PLL frequency not locked!\n"));
228 else
229 LOG(2,("DAC: PIX PLL frequency locked\n"));
230 DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); /*enable the PIXPLL*/
231
232 return B_OK;
233 }
234
gx50_dac_check_pix_pll(uint8 m,uint8 n,uint8 p)235 static status_t gx50_dac_check_pix_pll(uint8 m, uint8 n, uint8 p)
236 {
237 uint time = 0, count = 0;
238
239 /*reprogram (disable,select,wait for stability,enable)*/
240 DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/
241 VGAW(MISCW,((VGAR(MISCR)&0xF3)|0x8)); /*select PIXPLLC*/
242 DXIW(PIXPLLCM,(m)); /*set m value*/
243 DXIW(PIXPLLCN,(n)); /*set n value*/
244 DXIW(PIXPLLCP,(p)); /*set p value*/
245
246 /* give the PLL 1mS at least to get a lock */
247 time = 0;
248 while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 1000))
249 {
250 time++;
251 snooze(1);
252 }
253
254 /* no lock aquired, not useable */
255 if (time > 1000) return B_ERROR;
256
257 /* check if lock holds for at least 90% of the time */
258 for (time = 0, count = 0; time <= 1000; time++)
259 {
260 if(DXIR(PIXPLLSTAT)&0x40) count++;
261 snooze(1);
262 }
263 /* we have a winner */
264 if (count >= 900) return B_OK;
265
266 /* nogo, the PLL does not stabilize */
267 return B_ERROR;
268 }
269
gx50_dac_check_pix_pll_range(uint8 m,uint8 n,uint8 * p,uint8 * q)270 static status_t gx50_dac_check_pix_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
271 {
272 uint8 s=0, p_backup = *p;
273
274 /* preset no candidate, non working setting */
275 *q = 0;
276 /* preset lowest range filter */
277 *p &= 0x47;
278
279 /* iterate through all possible filtersettings */
280 DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/
281
282 for (s = 0; s < 8 ;s++)
283 {
284 if (gx50_dac_check_pix_pll(m, n, *p)== B_OK)
285 {
286 /* now check 3 closest lower and higher settings */
287 if ((gx50_dac_check_pix_pll(m, n - 3, *p)== B_OK) &&
288 (gx50_dac_check_pix_pll(m, n - 2, *p)== B_OK) &&
289 (gx50_dac_check_pix_pll(m, n - 1, *p)== B_OK) &&
290 (gx50_dac_check_pix_pll(m, n + 1, *p)== B_OK) &&
291 (gx50_dac_check_pix_pll(m, n + 2, *p)== B_OK) &&
292 (gx50_dac_check_pix_pll(m, n + 3, *p)== B_OK))
293 {
294 LOG(2,("DAC: found optimal working VCO filter: #%d\n",s));
295 /* preset first choice setting found */
296 *q = 1;
297 /* we are done */
298 DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); /*enable the PIXPLL*/
299 return B_OK;
300 }
301 else
302 {
303 LOG(2,("DAC: found critical but working VCO filter: #%d\n",s));
304 /* preset backup setting found */
305 *q = 2;
306 /* remember this setting */
307 p_backup = *p;
308 /* let's continue to see if a better filter exists */
309 }
310 }
311 /* new filtersetting to try */
312 *p += (1 << 3);
313 }
314
315 /* return the (last found) backup result, or the original p value */
316 *p = p_backup;
317 DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); /*enable the PIXPLL*/
318 /* we found only a non-optimal value */
319 if (*q == 2) return B_OK;
320
321 /* nothing worked at all */
322 LOG(2,("DAC: no working VCO filter found!\n"));
323 return B_ERROR;
324 }
325
326 /* find nearest valid pix pll */
gx00_dac_pix_pll_find(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result,uint8 test)327 status_t gx00_dac_pix_pll_find
328 (display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test)
329 {
330 switch (si->ps.card_type) {
331 case G550:
332 case G450: return g450_g550_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test);
333 case MIL2:
334 case MIL1: return milx_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result);
335 default: return g100_g400max_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test);
336 }
337 return B_ERROR;
338 }
339
340
341 /* find nearest valid pixel PLL setting: rewritten by rudolf */
milx_dac_pix_pll_find(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)342 static status_t milx_dac_pix_pll_find(
343 display_mode target, float* calc_pclk, uint8* m_result, uint8* n_result,
344 uint8* p_result)
345 {
346 int m = 0, n = 0, p = 0;
347 float error, error_best = INFINITY;
348 int best[3] = {0, 0, 0};
349 float f_vco, max_pclk;
350 float req_pclk = target.timing.pixel_clock / 1000.0;
351
352 LOG(4, ("DAC: MIL1/MIL2 TVP restrictions apply\n"));
353
354 /* determine the max. pixelclock for the current videomode */
355 switch (target.space)
356 {
357 case B_CMAP8:
358 max_pclk = si->ps.max_dac1_clock_8;
359 break;
360 case B_RGB15_LITTLE:
361 case B_RGB16_LITTLE:
362 max_pclk = si->ps.max_dac1_clock_16;
363 break;
364 case B_RGB24_LITTLE:
365 max_pclk = si->ps.max_dac1_clock_24;
366 break;
367 case B_RGB32_LITTLE:
368 max_pclk = si->ps.max_dac1_clock_32;
369 break;
370 default:
371 /* use fail-safe value */
372 max_pclk = si->ps.max_dac1_clock_32;
373 break;
374 }
375
376 /* Make sure the requested pixelclock is within the PLL's operational limits */
377 /* lower limit is min_pixel_vco divided by highest postscaler-factor */
378 if (req_pclk < (si->ps.min_pixel_vco / 8.0))
379 {
380 LOG(4, ("DAC: TVP clamping pixclock: requested %fMHz, set to %fMHz\n",
381 req_pclk, (float)(si->ps.min_pixel_vco / 8.0)));
382 req_pclk = (si->ps.min_pixel_vco / 8.0);
383 }
384 /* upper limit is given by pins in combination with current active mode */
385 if (req_pclk > max_pclk)
386 {
387 LOG(4, ("DAC: TVP clamping pixclock: requested %fMHz, set to %fMHz\n",
388 req_pclk, (float)max_pclk));
389 req_pclk = max_pclk;
390 }
391
392 /* iterate through all valid PLL postscaler settings */
393 for (p=0x01; p < 0x10; p = p<<1)
394 {
395 /* calculate the needed VCO frequency for this postscaler setting */
396 f_vco = req_pclk * p;
397
398 /* check if this is within range of the VCO specs */
399 if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco))
400 {
401 /* iterate trough all valid reference-frequency postscaler settings */
402 for (n = 3; n <= 25; n++)
403 {
404 /* calculate VCO postscaler setting for current setup.. */
405 m = (int)(((f_vco * n) / (8 * si->ps.f_ref)) + 0.5);
406 /* ..and check for validity */
407 if ((m < 3) || (m > 64)) continue;
408
409 /* find error in frequency this setting gives */
410 error = fabs(req_pclk - ((((8 * si->ps.f_ref) / n) * m) / p));
411
412 /* note the setting if best yet */
413 if (error < error_best)
414 {
415 error_best = error;
416 best[0]=m;
417 best[1]=n;
418 best[2]=p;
419 }
420 }
421 }
422 }
423
424 m = best[0];
425 n = best[1];
426 p = best[2];
427
428 f_vco = (((8 * si->ps.f_ref) / n) * m);
429 LOG(2, ("DAC: TVP pix VCO frequency found %fMhz\n", f_vco));
430
431 /* setup the scalers programming values for found optimum setting */
432 *calc_pclk = (f_vco / p);
433 *m_result = (65 - m);
434 *n_result = (65 - n);
435
436 switch (p)
437 {
438 case 1:
439 p = 0x00;
440 break;
441 case 2:
442 p = 0x01;
443 break;
444 case 4:
445 p = 0x02;
446 break;
447 case 8:
448 p = 0x03;
449 break;
450 }
451 *p_result = p;
452
453 /* display the found pixelclock values */
454 LOG(2, ("DAC: TVP pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
455 req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
456
457 return B_OK;
458 }
459
460
461 /* find nearest valid pixel PLL setting: rewritten by rudolf */
g100_g400max_dac_pix_pll_find(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result,uint8 test)462 static status_t g100_g400max_dac_pix_pll_find(
463 display_mode target, float* calc_pclk, uint8* m_result, uint8* n_result,
464 uint8* p_result, uint8 test)
465 {
466 int m = 0, n = 0, p = 0, m_max;
467 float error, error_best = INFINITY;
468 int best[3] = {0, 0, 0};
469 float f_vco, max_pclk;
470 float req_pclk = target.timing.pixel_clock/1000.0;
471
472 /* determine the max. reference-frequency postscaler setting for the
473 * current card (see G100, G200 and G400 specs). */
474 switch (si->ps.card_type)
475 {
476 case G100:
477 LOG(4, ("DAC: G100 restrictions apply\n"));
478 m_max = 7;
479 break;
480 case G200:
481 LOG(4, ("DAC: G200 restrictions apply\n"));
482 m_max = 7;
483 break;
484 default:
485 LOG(4, ("DAC: G400/G400MAX restrictions apply\n"));
486 m_max = 32;
487 break;
488 }
489
490 /* make sure the pixelPLL and the videoPLL have a little different settings to
491 * minimize distortions in the outputs due to crosstalk:
492 * do *not* change the videoPLL setting because it must be exact if TVout is enabled! */
493 /* Note:
494 * only modify the clock if we are actually going to set the mode */
495 if ((target.flags & DUALHEAD_BITS) && test)
496 {
497 LOG(4, ("DAC: dualhead mode active: modified requested pixelclock +1.5%%\n"));
498 req_pclk *= 1.015;
499 }
500
501 /* determine the max. pixelclock for the current videomode */
502 switch (target.space)
503 {
504 case B_CMAP8:
505 max_pclk = si->ps.max_dac1_clock_8;
506 break;
507 case B_RGB15_LITTLE:
508 case B_RGB16_LITTLE:
509 max_pclk = si->ps.max_dac1_clock_16;
510 break;
511 case B_RGB24_LITTLE:
512 max_pclk = si->ps.max_dac1_clock_24;
513 break;
514 case B_RGB32_LITTLE:
515 max_pclk = si->ps.max_dac1_clock_32;
516 break;
517 default:
518 /* use fail-safe value */
519 max_pclk = si->ps.max_dac1_clock_32;
520 break;
521 }
522 /* if some dualhead mode is active, an extra restriction might apply */
523 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
524 max_pclk = si->ps.max_dac1_clock_32dh;
525
526 /* Make sure the requested pixelclock is within the PLL's operational limits */
527 /* lower limit is min_pixel_vco divided by highest postscaler-factor */
528 if (req_pclk < (si->ps.min_pixel_vco / 8.0))
529 {
530 LOG(4, ("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
531 req_pclk, (float)(si->ps.min_pixel_vco / 8.0)));
532 req_pclk = (si->ps.min_pixel_vco / 8.0);
533 }
534 /* upper limit is given by pins in combination with current active mode */
535 if (req_pclk > max_pclk)
536 {
537 LOG(4, ("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
538 req_pclk, (float)max_pclk));
539 req_pclk = max_pclk;
540 }
541
542 /* iterate through all valid PLL postscaler settings */
543 for (p=0x01; p < 0x10; p = p<<1)
544 {
545 /* calculate the needed VCO frequency for this postscaler setting */
546 f_vco = req_pclk * p;
547
548 /* check if this is within range of the VCO specs */
549 if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco))
550 {
551 /* iterate trough all valid reference-frequency postscaler settings */
552 for (m = 2; m <= m_max; m++)
553 {
554 /* calculate VCO postscaler setting for current setup.. */
555 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
556 /* ..and check for validity */
557 if ((n < 8) || (n > 128)) continue;
558
559 /* find error in frequency this setting gives */
560 error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p));
561
562 /* note the setting if best yet */
563 if (error < error_best)
564 {
565 error_best = error;
566 best[0]=m;
567 best[1]=n;
568 best[2]=p;
569 }
570 }
571 }
572 }
573
574 /* setup the scalers programming values for found optimum setting */
575 m=best[0] - 1;
576 n=best[1] - 1;
577 p=best[2] - 1;
578
579 /* calc the needed PLL loopbackfilter setting belonging to current VCO speed,
580 * for the current card (see G100, G200 and G400 specs). */
581 f_vco = (si->ps.f_ref / (m + 1)) * (n + 1);
582 LOG(2, ("DAC: pix VCO frequency found %fMhz\n", f_vco));
583
584 switch (si->ps.card_type)
585 {
586 case G100:
587 case G200:
588 for (;;)
589 {
590 if (f_vco >= 180) {p |= (0x03 << 3); break;};
591 if (f_vco >= 140) {p |= (0x02 << 3); break;};
592 if (f_vco >= 100) {p |= (0x01 << 3); break;};
593 break;
594 }
595 break;
596 default:
597 for (;;)
598 {
599 if (f_vco >= 240) {p |= (0x03 << 3); break;};
600 if (f_vco >= 170) {p |= (0x02 << 3); break;};
601 if (f_vco >= 110) {p |= (0x01 << 3); break;};
602 break;
603 }
604 break;
605 }
606
607 /* return the results */
608 *calc_pclk = f_vco / ((p & 0x07) + 1);
609 *m_result = m;
610 *n_result = n;
611 *p_result = p;
612
613 /* display the found pixelclock values */
614 LOG(2, ("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
615 req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
616
617 return B_OK;
618 }
619
620
621 /* find nearest valid pixel PLL setting: rewritten by rudolf */
g450_g550_dac_pix_pll_find(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result,uint8 test)622 static status_t g450_g550_dac_pix_pll_find
623 (display_mode target, float* calc_pclk, uint8* m_result, uint8* n_result,
624 uint8* p_result, uint8 test)
625 {
626 int m = 0, n = 0;
627 uint8 p = 0, q = 0;
628 float error, error_best = INFINITY;
629 int best[3] = {0, 0, 0};
630 float f_vco, max_pclk;
631 float req_pclk = target.timing.pixel_clock / 1000.0;
632
633 LOG(4, ("DAC: G450/G550 restrictions apply\n"));
634
635 /* determine the max. pixelclock for the current videomode */
636 switch (target.space)
637 {
638 case B_CMAP8:
639 max_pclk = si->ps.max_dac1_clock_8;
640 break;
641 case B_RGB15_LITTLE:
642 case B_RGB16_LITTLE:
643 max_pclk = si->ps.max_dac1_clock_16;
644 break;
645 case B_RGB24_LITTLE:
646 max_pclk = si->ps.max_dac1_clock_24;
647 break;
648 case B_RGB32_LITTLE:
649 max_pclk = si->ps.max_dac1_clock_32;
650 break;
651 default:
652 /* use fail-safe value */
653 max_pclk = si->ps.max_dac1_clock_32;
654 break;
655 }
656 /* if some dualhead mode is active, an extra restriction might apply */
657 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
658 max_pclk = si->ps.max_dac1_clock_32dh;
659
660 /* Make sure the requested pixelclock is within the PLL's operational limits */
661 /* lower limit is min_pixel_vco divided by highest postscaler-factor */
662 if (req_pclk < (si->ps.min_pixel_vco / 16.0))
663 {
664 LOG(4, ("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
665 req_pclk, (float)(si->ps.min_pixel_vco / 16.0)));
666 req_pclk = (si->ps.min_pixel_vco / 16.0);
667 }
668 /* upper limit is given by pins in combination with current active mode */
669 if (req_pclk > max_pclk)
670 {
671 LOG(4, ("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
672 req_pclk, (float)max_pclk));
673 req_pclk = max_pclk;
674 }
675
676 /* iterate through all valid PLL postscaler settings */
677 for (p=0x01; p < 0x20; p = p<<1)
678 {
679 /* calculate the needed VCO frequency for this postscaler setting */
680 f_vco = req_pclk * p;
681
682 /* check if this is within range of the VCO specs */
683 if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco))
684 {
685 /* iterate trough all valid reference-frequency postscaler settings */
686 for (m = 2; m <= 32; m++)
687 {
688 /* calculate VCO postscaler setting for current setup.. */
689 n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5);
690 /* ..and check for validity, BUT:
691 * Keep in mind that we need to be able to test n-3 ... n+3! */
692 if ((n < (8 + 3)) || (n > (128 - 3))) continue;
693
694 /* find error in frequency this setting gives */
695 error = fabs(req_pclk - ((((si->ps.f_ref * 2)/ m) * n) / p));
696
697 /* note the setting if best yet */
698 if (error < error_best)
699 {
700 error_best = error;
701 best[0]=m;
702 best[1]=n;
703 best[2]=p;
704 }
705 }
706 }
707 }
708
709 /* setup the scalers programming values for found optimum setting */
710 m=best[0] - 1;
711 n=best[1] - 2;
712 switch (best[2])
713 {
714 case 1:
715 p = 0x40;
716 break;
717 case 2:
718 p = 0x00;
719 break;
720 case 4:
721 p = 0x01;
722 break;
723 case 8:
724 p = 0x02;
725 break;
726 case 16:
727 p = 0x03;
728 break;
729 }
730
731 /* log the closest VCO speed found */
732 f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2);
733 LOG(2, ("DAC: pix VCO frequency found %fMhz\n", f_vco));
734
735 /* now find the filtersetting that matches best with this frequency by testing.
736 * for now we assume this routine succeeds to get us a stable setting */
737 if (test)
738 gx50_dac_check_pix_pll_range(m, n, &p, &q);
739 else
740 LOG(2, ("DAC: Not testing G450/G550 VCO feedback filters\n"));
741
742 /* return the results */
743 *calc_pclk = f_vco / best[2];
744 *m_result = m;
745 *n_result = n;
746 *p_result = p;
747
748 /* display the found pixelclock values */
749 LOG(2, ("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
750 req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
751
752 return B_OK;
753 }
754
755
756 /* find nearest valid system PLL setting */
g100_g400max_dac_sys_pll_find(float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)757 static status_t g100_g400max_dac_sys_pll_find(
758 float req_sclk, float* calc_sclk, uint8* m_result, uint8* n_result,
759 uint8 * p_result)
760 {
761 int m = 0, n = 0, p = 0, m_max;
762 float error, error_best = INFINITY;
763 int best[3] = {0, 0, 0};
764 float f_vco;
765
766 /* determine the max. reference-frequency postscaler setting for the
767 * current card (see G100, G200 and G400 specs). */
768 switch (si->ps.card_type)
769 {
770 case G100:
771 LOG(4, ("DAC: G100 restrictions apply\n"));
772 m_max = 7;
773 break;
774 case G200:
775 LOG(4, ("DAC: G200 restrictions apply\n"));
776 m_max = 7;
777 break;
778 default:
779 LOG(4, ("DAC: G400/G400MAX restrictions apply\n"));
780 m_max = 32;
781 break;
782 }
783
784 /* Make sure the requested systemclock is within the PLL's operational limits */
785 /* lower limit is min_system_vco divided by highest postscaler-factor */
786 if (req_sclk < (si->ps.min_system_vco / 8.0))
787 {
788 LOG(4, ("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
789 req_sclk, (float)(si->ps.min_system_vco / 8.0)));
790 req_sclk = (si->ps.min_system_vco / 8.0);
791 }
792 /* upper limit is max_system_vco */
793 if (req_sclk > si->ps.max_system_vco)
794 {
795 LOG(4, ("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
796 req_sclk, (float)si->ps.max_system_vco));
797 req_sclk = si->ps.max_system_vco;
798 }
799
800 /* iterate through all valid PLL postscaler settings */
801 for (p=0x01; p < 0x10; p = p<<1)
802 {
803 /* calculate the needed VCO frequency for this postscaler setting */
804 f_vco = req_sclk * p;
805
806 /* check if this is within range of the VCO specs */
807 if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco))
808 {
809 /* iterate trough all valid reference-frequency postscaler settings */
810 for (m = 2; m <= m_max; m++)
811 {
812 /* calculate VCO postscaler setting for current setup.. */
813 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
814 /* ..and check for validity */
815 if ((n < 8) || (n > 128)) continue;
816
817 /* find error in frequency this setting gives */
818 error = fabs(req_sclk - (((si->ps.f_ref / m) * n) / p));
819
820 /* note the setting if best yet */
821 if (error < error_best)
822 {
823 error_best = error;
824 best[0]=m;
825 best[1]=n;
826 best[2]=p;
827 }
828 }
829 }
830 }
831
832 /* setup the scalers programming values for found optimum setting */
833 m=best[0] - 1;
834 n=best[1] - 1;
835 p=best[2] - 1;
836
837 /* calc the needed PLL loopbackfilter setting belonging to current VCO speed,
838 * for the current card (see G100, G200 and G400 specs). */
839 f_vco = (si->ps.f_ref / (m + 1)) * (n + 1);
840 LOG(2, ("DAC: sys VCO frequency found %fMhz\n", f_vco));
841
842 switch (si->ps.card_type)
843 {
844 case G100:
845 case G200:
846 for (;;)
847 {
848 if (f_vco >= 180) {p |= (0x03 << 3); break;};
849 if (f_vco >= 140) {p |= (0x02 << 3); break;};
850 if (f_vco >= 100) {p |= (0x01 << 3); break;};
851 break;
852 }
853 break;
854 default:
855 for (;;)
856 {
857 if (f_vco >= 240) {p |= (0x03 << 3); break;};
858 if (f_vco >= 170) {p |= (0x02 << 3); break;};
859 if (f_vco >= 110) {p |= (0x01 << 3); break;};
860 break;
861 }
862 break;
863 }
864
865 /* return the results */
866 *calc_sclk = f_vco / ((p & 0x07) + 1);
867 *m_result = m;
868 *n_result = n;
869 *p_result = p;
870
871 /* display the found pixelclock values */
872 LOG(2, ("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
873 req_sclk, *calc_sclk, *m_result, *n_result, *p_result));
874
875 return B_OK;
876 }
877
878
gx50_dac_check_sys_pll(uint8 m,uint8 n,uint8 p)879 static status_t gx50_dac_check_sys_pll(uint8 m, uint8 n, uint8 p)
880 {
881 uint time = 0, count = 0;
882
883 /* program the new clock */
884 DXIW(SYSPLLM, m);
885 DXIW(SYSPLLN, n);
886 DXIW(SYSPLLP, p);
887
888 /* Wait for the SYSPLL frequency to lock until timeout occurs */
889 time = 0;
890 while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 1000))
891 {
892 time++;
893 snooze(1);
894 }
895
896 /* no lock aquired, not useable */
897 if (time > 1000) return B_ERROR;
898
899 /* check if lock holds for at least 90% of the time */
900 for (time = 0, count = 0; time <= 1000; time++)
901 {
902 if(DXIR(SYSPLLSTAT)&0x40) count++;
903 snooze(1);
904 }
905 /* we have a winner */
906 if (count >= 900) return B_OK;
907
908 /* nogo, the PLL does not stabilize */
909 return B_ERROR;
910 }
911
gx50_dac_check_sys_pll_range(uint8 m,uint8 n,uint8 * p,uint8 * q)912 static status_t gx50_dac_check_sys_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
913 {
914 uint8 s=0, p_backup = *p;
915
916 /* preset no candidate, non working setting */
917 *q = 0;
918 /* preset lowest range filter */
919 *p &= 0x47;
920
921 /* iterate through all possible filtersettings */
922 for (s = 0; s < 8 ;s++)
923 {
924 if (gx50_dac_check_sys_pll(m, n, *p)== B_OK)
925 {
926 /* now check 3 closest lower and higher settings */
927 if ((gx50_dac_check_sys_pll(m, n - 3, *p)== B_OK) &&
928 (gx50_dac_check_sys_pll(m, n - 2, *p)== B_OK) &&
929 (gx50_dac_check_sys_pll(m, n - 1, *p)== B_OK) &&
930 (gx50_dac_check_sys_pll(m, n + 1, *p)== B_OK) &&
931 (gx50_dac_check_sys_pll(m, n + 2, *p)== B_OK) &&
932 (gx50_dac_check_sys_pll(m, n + 3, *p)== B_OK))
933 {
934 LOG(2,("DAC: found optimal working VCO filter: #%d\n",s));
935 /* preset first choice setting found */
936 *q = 1;
937 /* we are done */
938 return B_OK;
939 }
940 else
941 {
942 LOG(2,("DAC: found critical but working VCO filter: #%d\n",s));
943 /* preset backup setting found */
944 *q = 2;
945 /* remember this setting */
946 p_backup = *p;
947 /* let's continue to see if a better filter exists */
948 }
949 }
950 /* new filtersetting to try */
951 *p += (1 << 3);
952 }
953
954 /* return the (last found) backup result, or the original p value */
955 *p = p_backup;
956 /* we found only a non-optimal value */
957 if (*q == 2) return B_OK;
958
959 /* nothing worked at all */
960 LOG(2, ("DAC: no working VCO filter found!\n"));
961 return B_ERROR;
962 }
963
964
965 /* find nearest valid system PLL setting */
g450_g550_dac_sys_pll_find(float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)966 static status_t g450_g550_dac_sys_pll_find(
967 float req_sclk, float* calc_sclk, uint8* m_result, uint8* n_result,
968 uint8* p_result)
969 {
970 int m = 0, n = 0;
971 uint8 p = 0, q = 0;
972 float error, error_best = INFINITY;
973 int best[3] = {0, 0, 0};
974 float f_vco;
975
976 LOG(4, ("DAC: G450/G550 restrictions apply\n"));
977
978 /* Make sure the requested pixelclock is within the PLL's operational limits */
979 /* lower limit is min_system_vco divided by highest postscaler-factor */
980 if (req_sclk < (si->ps.min_system_vco / 16.0))
981 {
982 LOG(4, ("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
983 req_sclk, (float)(si->ps.min_system_vco / 16.0)));
984 req_sclk = (si->ps.min_system_vco / 16.0);
985 }
986 /* upper limit is max_system_vco */
987 if (req_sclk > si->ps.max_system_vco)
988 {
989 LOG(4, ("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
990 req_sclk, (float)si->ps.max_system_vco));
991 req_sclk = si->ps.max_system_vco;
992 }
993
994 /* iterate through all valid PLL postscaler settings */
995 for (p=0x01; p < 0x20; p = p<<1)
996 {
997 /* calculate the needed VCO frequency for this postscaler setting */
998 f_vco = req_sclk * p;
999
1000 /* check if this is within range of the VCO specs */
1001 if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco))
1002 {
1003 /* iterate trough all valid reference-frequency postscaler settings */
1004 for (m = 2; m <= 32; m++)
1005 {
1006 /* calculate VCO postscaler setting for current setup.. */
1007 n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5);
1008 /* ..and check for validity, BUT:
1009 * Keep in mind that we need to be able to test n-3 ... n+3! */
1010 if ((n < (8 + 3)) || (n > (128 - 3))) continue;
1011
1012 /* find error in frequency this setting gives */
1013 error = fabs(req_sclk - ((((si->ps.f_ref * 2)/ m) * n) / p));
1014
1015 /* note the setting if best yet */
1016 if (error < error_best)
1017 {
1018 error_best = error;
1019 best[0]=m;
1020 best[1]=n;
1021 best[2]=p;
1022 }
1023 }
1024 }
1025 }
1026
1027 /* setup the scalers programming values for found optimum setting */
1028 m=best[0] - 1;
1029 n=best[1] - 2;
1030 switch(best[2])
1031 {
1032 case 1:
1033 p = 0x40;
1034 break;
1035 case 2:
1036 p = 0x00;
1037 break;
1038 case 4:
1039 p = 0x01;
1040 break;
1041 case 8:
1042 p = 0x02;
1043 break;
1044 case 16:
1045 p = 0x03;
1046 break;
1047 }
1048
1049 /* log the closest VCO speed found */
1050 f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2);
1051 LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco));
1052
1053 /* now find the filtersetting that matches best with this frequency by testing.
1054 * for now we assume this routine succeeds to get us a stable setting */
1055 gx50_dac_check_sys_pll_range(m, n, &p, &q);
1056
1057 /* return the results */
1058 *calc_sclk = f_vco / best[2];
1059 *m_result = m;
1060 *n_result = n;
1061 *p_result = p;
1062
1063 /* display the found pixelclock values */
1064 LOG(2,("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
1065 req_sclk, *calc_sclk, *m_result, *n_result, *p_result));
1066
1067 return B_OK;
1068 }
1069
1070 /*set up system pll - NB mclk is memory clock */
g100_dac_set_sys_pll()1071 status_t g100_dac_set_sys_pll()
1072 {
1073 /* values for DAC sys pll registers */
1074 uint8 m, n, p;
1075 uint time = 0;
1076 uint32 temp;
1077 float calc_sclk;
1078
1079 LOG(1,("DAC: Setting up G100 system clock\n"));
1080 g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1081
1082 /* reprogram the clock - set PCI/AGP, program, set to programmed */
1083 /* disable the SYSPLL */
1084 CFGW(OPTION, CFGR(OPTION) | 0x04);
1085 /* select the PCI/AGP clock */
1086 CFGW(OPTION, CFGR(OPTION) & 0xfffffffc);
1087 /* enable the SYSPLL */
1088 CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1089
1090 /* program the new clock */
1091 DXIW(SYSPLLM, m);
1092 DXIW(SYSPLLN, n);
1093 DXIW(SYSPLLP, p);
1094
1095 /* Wait for the SYSPLL frequency to lock until timeout occurs */
1096 while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1097 {
1098 time++;
1099 snooze(1);
1100 }
1101
1102 if (time > 2000)
1103 LOG(2,("DAC: sys PLL frequency not locked!\n"));
1104 else
1105 LOG(2,("DAC: sys PLL frequency locked\n"));
1106
1107 /* disable the SYSPLL */
1108 CFGW(OPTION, CFGR(OPTION) | 0x04);
1109 /* setup Gclk, Mclk and FMclk divisors according to PINS */
1110 temp = (CFGR(OPTION) & 0xffffff27);
1111 if (si->ps.v3_clk_div & 0x01) temp |= 0x08;
1112 if (si->ps.v3_clk_div & 0x02) temp |= 0x10;
1113 if (si->ps.v3_clk_div & 0x04) temp |= 0x80;
1114 /* fixme: swapPLL can only be done when the rest of the driver respects this also! */
1115 //never used AFAIK:
1116 //if (si->ps.v3_clk_div & 0x08) temp |= 0x40;
1117 /* select the SYSPLL as system clock source */
1118 temp |= 0x01;
1119 CFGW(OPTION, temp);
1120 /* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1121 CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1122
1123 return B_OK;
1124 }
1125
1126 /*set up system pll - NB mclk is memory clock */
g200_dac_set_sys_pll()1127 status_t g200_dac_set_sys_pll()
1128 {
1129 /* values for DAC sys pll registers */
1130 uint8 m, n, p;
1131 uint time = 0;
1132 uint32 temp;
1133 float calc_sclk;
1134
1135 LOG(1,("DAC: Setting up G200 system clock\n"));
1136 g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1137
1138 /* reprogram the clock - set PCI/AGP, program, set to programmed */
1139 /* disable the SYSPLL */
1140 CFGW(OPTION, CFGR(OPTION) | 0x04);
1141 /* select the PCI/AGP clock */
1142 CFGW(OPTION, CFGR(OPTION) & 0xfffffffc);
1143 /* enable the SYSPLL */
1144 CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1145
1146 /* program the new clock */
1147 DXIW(SYSPLLM, m);
1148 DXIW(SYSPLLN, n);
1149 DXIW(SYSPLLP, p);
1150
1151 /* Wait for the SYSPLL frequency to lock until timeout occurs */
1152 while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1153 {
1154 time++;
1155 snooze(1);
1156 }
1157
1158 if (time > 2000)
1159 LOG(2,("DAC: sys PLL frequency not locked!\n"));
1160 else
1161 LOG(2,("DAC: sys PLL frequency locked\n"));
1162
1163 /* disable the SYSPLL */
1164 CFGW(OPTION, CFGR(OPTION) | 0x04);
1165 /* setup Wclk divisor and enable/disable Wclk, Gclk and Mclk divisors
1166 * according to PINS */
1167 temp = (CFGR(OPTION2) & 0x00383000);
1168 if (si->ps.v3_option2_reg & 0x04) temp |= 0x00004000;
1169 if (si->ps.v3_option2_reg & 0x08) temp |= 0x00008000;
1170 if (si->ps.v3_option2_reg & 0x10) temp |= 0x00010000;
1171 if (si->ps.v3_option2_reg & 0x20) temp |= 0x00020000;
1172 CFGW(OPTION2, temp);
1173 /* setup Gclk and Mclk divisors according to PINS */
1174 temp = (CFGR(OPTION) & 0xffffff27);
1175 if (si->ps.v3_clk_div & 0x01) temp |= 0x08;
1176 if (si->ps.v3_clk_div & 0x02) temp |= 0x10;
1177 /* fixme: swapPLL can only be done when the rest of the driver respects this also! */
1178 //never used AFAIK:
1179 //if (si->ps.v3_clk_div & 0x08) temp |= 0x40;
1180 /* select the SYSPLL as system clock source */
1181 temp |= 0x01;
1182 CFGW(OPTION, temp);
1183 /* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1184 CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1185
1186 return B_OK;
1187 }
1188
1189 /*set up system pll - NB mclk is memory clock */
g400_dac_set_sys_pll()1190 status_t g400_dac_set_sys_pll()
1191 {
1192 /* values for DAC sys pll registers */
1193 uint8 m, n, p;
1194 uint time = 0;
1195 float calc_sclk;
1196
1197 LOG(1,("DAC: Setting up G400/G400MAX system clock\n"));
1198 g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1199
1200 /* reprogram the clock - set PCI/AGP, program, set to programmed */
1201 /* clear, so don't o/clock addons */
1202 CFGW(OPTION2, 0);
1203 /* disable the SYSPLL */
1204 CFGW(OPTION, CFGR(OPTION) | 0x04);
1205 /* select the PCI/AGP clock */
1206 CFGW(OPTION3, 0);
1207 /* enable the SYSPLL */
1208 CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1209
1210 /* program the new clock */
1211 DXIW(SYSPLLM, m);
1212 DXIW(SYSPLLN, n);
1213 DXIW(SYSPLLP, p);
1214
1215 /* Wait for the SYSPLL frequency to lock until timeout occurs */
1216 while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1217 {
1218 time++;
1219 snooze(1);
1220 }
1221
1222 if (time > 2000)
1223 LOG(2,("DAC: sys PLL frequency not locked!\n"));
1224 else
1225 LOG(2,("DAC: sys PLL frequency locked\n"));
1226
1227 /* disable the SYSPLL */
1228 CFGW(OPTION, CFGR(OPTION) | 0x04);
1229 /* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */
1230 CFGW(OPTION3, si->ps.option3_reg);
1231 /* make sure the PLLs are not swapped (set default config) */
1232 CFGW(OPTION, CFGR(OPTION) & 0xffffffbf);
1233 /* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1234 CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1235
1236 return B_OK;
1237 }
1238
1239 /*set up system pll - NB mclk is memory clock */
g450_dac_set_sys_pll()1240 status_t g450_dac_set_sys_pll()
1241 {
1242 /* values for DAC sys pll registers */
1243 uint8 m, n, p;
1244 uint time = 0;
1245 float calc_sclk;
1246
1247 LOG(1,("DAC: Setting up G450/G550 system clock\n"));
1248 /* reprogram the clock - set PCI/AGP, program, set to programmed */
1249 /* clear, so don't o/clock addons */
1250 CFGW(OPTION2, 0);
1251 /* setup OPTION via pins */
1252 CFGW(OPTION, si->ps.option_reg);
1253 /* disable the SYSPLL */
1254 CFGW(OPTION, CFGR(OPTION) | 0x04);
1255 /* select the PCI/AGP clock */
1256 CFGW(OPTION3, 0);
1257 /* enable the SYSPLL */
1258 CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1259
1260 /* this routine also tests the filters, so it actually programs the clock already */
1261 g450_g550_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1262
1263 /* program the new clock */
1264 DXIW(SYSPLLM, m);
1265 DXIW(SYSPLLN, n);
1266 DXIW(SYSPLLP, p);
1267
1268 /* Wait for the SYSPLL frequency to lock until timeout occurs */
1269 while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1270 {
1271 time++;
1272 snooze(1);
1273 }
1274
1275 if (time > 2000)
1276 LOG(2,("DAC: sys PLL frequency not locked!\n"));
1277 else
1278 LOG(2,("DAC: sys PLL frequency locked\n"));
1279
1280 /* disable the SYSPLL */
1281 CFGW(OPTION, CFGR(OPTION) | 0x04);
1282 /* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */
1283 CFGW(OPTION3, si->ps.option3_reg);
1284 /* setup option2 via pins */
1285 CFGW(OPTION2, si->ps.option2_reg);
1286 /* make sure the PLLs are not swapped (set default config) */
1287 /* fixme: swapPLL can only be done when the rest of the driver respects this also!
1288 * (never used AFAIK) */
1289 CFGW(OPTION, CFGR(OPTION) & 0xffffffbf);
1290 /* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1291 CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1292
1293 return B_OK;
1294 }
1295