xref: /haiku/src/add-ons/accelerants/matrox/engine/mga_dac.c (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
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)*/
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*/
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  */
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 
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 
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 */
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 /* find nearest valid pixel PLL setting: rewritten by rudolf */
341 static status_t milx_dac_pix_pll_find(
342 	display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)
343 {
344 	int m = 0, n = 0, p = 0;
345 	float error, error_best = 999999999;
346 	int best[3];
347 	float f_vco, max_pclk;
348 	float req_pclk = target.timing.pixel_clock/1000.0;
349 
350 	LOG(4,("DAC: MIL1/MIL2 TVP restrictions apply\n"));
351 
352 	/* determine the max. pixelclock for the current videomode */
353 	switch (target.space)
354 	{
355 		case B_CMAP8:
356 			max_pclk = si->ps.max_dac1_clock_8;
357 			break;
358 		case B_RGB15_LITTLE:
359 		case B_RGB16_LITTLE:
360 			max_pclk = si->ps.max_dac1_clock_16;
361 			break;
362 		case B_RGB24_LITTLE:
363 			max_pclk = si->ps.max_dac1_clock_24;
364 			break;
365 		case B_RGB32_LITTLE:
366 			max_pclk = si->ps.max_dac1_clock_32;
367 			break;
368 		default:
369 			/* use fail-safe value */
370 			max_pclk = si->ps.max_dac1_clock_32;
371 			break;
372 	}
373 
374 	/* Make sure the requested pixelclock is within the PLL's operational limits */
375 	/* lower limit is min_pixel_vco divided by highest postscaler-factor */
376 	if (req_pclk < (si->ps.min_pixel_vco / 8.0))
377 	{
378 		LOG(4,("DAC: TVP clamping pixclock: requested %fMHz, set to %fMHz\n",
379 										req_pclk, (float)(si->ps.min_pixel_vco / 8.0)));
380 		req_pclk = (si->ps.min_pixel_vco / 8.0);
381 	}
382 	/* upper limit is given by pins in combination with current active mode */
383 	if (req_pclk > max_pclk)
384 	{
385 		LOG(4,("DAC: TVP clamping pixclock: requested %fMHz, set to %fMHz\n",
386 														req_pclk, (float)max_pclk));
387 		req_pclk = max_pclk;
388 	}
389 
390 	/* iterate through all valid PLL postscaler settings */
391 	for (p=0x01; p < 0x10; p = p<<1)
392 	{
393 		/* calculate the needed VCO frequency for this postscaler setting */
394 		f_vco = req_pclk * p;
395 
396 		/* check if this is within range of the VCO specs */
397 		if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco))
398 		{
399 			/* iterate trough all valid reference-frequency postscaler settings */
400 			for (n = 3; n <= 25; n++)
401 			{
402 				/* calculate VCO postscaler setting for current setup.. */
403 				m = (int)(((f_vco * n) / (8 * si->ps.f_ref)) + 0.5);
404 				/* ..and check for validity */
405 				if ((m < 3) || (m > 64))	continue;
406 
407 				/* find error in frequency this setting gives */
408 				error = fabs(req_pclk - ((((8 * si->ps.f_ref) / n) * m) / p));
409 
410 				/* note the setting if best yet */
411 				if (error < error_best)
412 				{
413 					error_best = error;
414 					best[0]=m;
415 					best[1]=n;
416 					best[2]=p;
417 				}
418 			}
419 		}
420 	}
421 
422 	m = best[0];
423 	n = best[1];
424 	p = best[2];
425 
426 	f_vco = (((8 * si->ps.f_ref) / n) * m);
427 	LOG(2,("DAC: TVP pix VCO frequency found %fMhz\n", f_vco));
428 
429 	/* setup the scalers programming values for found optimum setting */
430 	*calc_pclk = (f_vco / p);
431 	*m_result = (65 - m);
432 	*n_result = (65 - n);
433 
434 	switch(p)
435 	{
436 	case 1:
437 		p = 0x00;
438 		break;
439 	case 2:
440 		p = 0x01;
441 		break;
442 	case 4:
443 		p = 0x02;
444 		break;
445 	case 8:
446 		p = 0x03;
447 		break;
448 	}
449 	*p_result = p;
450 
451 	/* display the found pixelclock values */
452 	LOG(2,("DAC: TVP pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
453 		req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
454 
455 	return B_OK;
456 }
457 
458 /* find nearest valid pixel PLL setting: rewritten by rudolf */
459 static status_t g100_g400max_dac_pix_pll_find(
460 	display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test)
461 {
462 	int m = 0, n = 0, p = 0, m_max;
463 	float error, error_best = 999999999;
464 	int best[3];
465 	float f_vco, max_pclk;
466 	float req_pclk = target.timing.pixel_clock/1000.0;
467 
468 	/* determine the max. reference-frequency postscaler setting for the
469 	 * current card (see G100, G200 and G400 specs). */
470 	switch(si->ps.card_type)
471 	{
472 	case G100:
473 		LOG(4,("DAC: G100 restrictions apply\n"));
474 		m_max = 7;
475 		break;
476 	case G200:
477 		LOG(4,("DAC: G200 restrictions apply\n"));
478 		m_max = 7;
479 		break;
480 	default:
481 		LOG(4,("DAC: G400/G400MAX restrictions apply\n"));
482 		m_max = 32;
483 		break;
484 	}
485 
486 	/* make sure the pixelPLL and the videoPLL have a little different settings to
487 	 * minimize distortions in the outputs due to crosstalk:
488 	 * do *not* change the videoPLL setting because it must be exact if TVout is enabled! */
489 	/* Note:
490 	 * only modify the clock if we are actually going to set the mode */
491 	if ((target.flags & DUALHEAD_BITS) && test)
492 	{
493 		LOG(4,("DAC: dualhead mode active: modified requested pixelclock +1.5%%\n"));
494 		req_pclk *= 1.015;
495 	}
496 
497 	/* determine the max. pixelclock for the current videomode */
498 	switch (target.space)
499 	{
500 		case B_CMAP8:
501 			max_pclk = si->ps.max_dac1_clock_8;
502 			break;
503 		case B_RGB15_LITTLE:
504 		case B_RGB16_LITTLE:
505 			max_pclk = si->ps.max_dac1_clock_16;
506 			break;
507 		case B_RGB24_LITTLE:
508 			max_pclk = si->ps.max_dac1_clock_24;
509 			break;
510 		case B_RGB32_LITTLE:
511 			max_pclk = si->ps.max_dac1_clock_32;
512 			break;
513 		default:
514 			/* use fail-safe value */
515 			max_pclk = si->ps.max_dac1_clock_32;
516 			break;
517 	}
518 	/* if some dualhead mode is active, an extra restriction might apply */
519 	if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
520 		max_pclk = si->ps.max_dac1_clock_32dh;
521 
522 	/* Make sure the requested pixelclock is within the PLL's operational limits */
523 	/* lower limit is min_pixel_vco divided by highest postscaler-factor */
524 	if (req_pclk < (si->ps.min_pixel_vco / 8.0))
525 	{
526 		LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
527 										req_pclk, (float)(si->ps.min_pixel_vco / 8.0)));
528 		req_pclk = (si->ps.min_pixel_vco / 8.0);
529 	}
530 	/* upper limit is given by pins in combination with current active mode */
531 	if (req_pclk > max_pclk)
532 	{
533 		LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
534 														req_pclk, (float)max_pclk));
535 		req_pclk = max_pclk;
536 	}
537 
538 	/* iterate through all valid PLL postscaler settings */
539 	for (p=0x01; p < 0x10; p = p<<1)
540 	{
541 		/* calculate the needed VCO frequency for this postscaler setting */
542 		f_vco = req_pclk * p;
543 
544 		/* check if this is within range of the VCO specs */
545 		if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco))
546 		{
547 			/* iterate trough all valid reference-frequency postscaler settings */
548 			for (m = 2; m <= m_max; m++)
549 			{
550 				/* calculate VCO postscaler setting for current setup.. */
551 				n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
552 				/* ..and check for validity */
553 				if ((n < 8) || (n > 128))	continue;
554 
555 				/* find error in frequency this setting gives */
556 				error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p));
557 
558 				/* note the setting if best yet */
559 				if (error < error_best)
560 				{
561 					error_best = error;
562 					best[0]=m;
563 					best[1]=n;
564 					best[2]=p;
565 				}
566 			}
567 		}
568 	}
569 
570 	/* setup the scalers programming values for found optimum setting */
571 	m=best[0] - 1;
572 	n=best[1] - 1;
573 	p=best[2] - 1;
574 
575 	/* calc the needed PLL loopbackfilter setting belonging to current VCO speed,
576 	 * for the current card (see G100, G200 and G400 specs). */
577 	f_vco = (si->ps.f_ref / (m + 1)) * (n + 1);
578 	LOG(2,("DAC: pix VCO frequency found %fMhz\n", f_vco));
579 
580 	switch(si->ps.card_type)
581 	{
582 	case G100:
583 	case G200:
584 		for(;;)
585 		{
586 			if (f_vco >= 180) {p |= (0x03 << 3); break;};
587 			if (f_vco >= 140) {p |= (0x02 << 3); break;};
588 			if (f_vco >= 100) {p |= (0x01 << 3); break;};
589 			break;
590 		}
591 		break;
592 	default:
593 		for(;;)
594 		{
595 			if (f_vco >= 240) {p |= (0x03 << 3); break;};
596 			if (f_vco >= 170) {p |= (0x02 << 3); break;};
597 			if (f_vco >= 110) {p |= (0x01 << 3); break;};
598 			break;
599 		}
600 		break;
601 	}
602 
603 	/* return the results */
604 	*calc_pclk = f_vco / ((p & 0x07) + 1);
605 	*m_result = m;
606 	*n_result = n;
607 	*p_result = p;
608 
609 	/* display the found pixelclock values */
610 	LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
611 		req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
612 
613 	return B_OK;
614 }
615 
616 /* find nearest valid pixel PLL setting: rewritten by rudolf */
617 static status_t g450_g550_dac_pix_pll_find
618 	(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test)
619 {
620 	int m = 0, n = 0;
621 	uint8 p = 0, q = 0;
622 	float error, error_best = 999999999;
623 	int best[3];
624 	float f_vco, max_pclk;
625 	float req_pclk = target.timing.pixel_clock/1000.0;
626 
627 	LOG(4,("DAC: G450/G550 restrictions apply\n"));
628 
629 	/* determine the max. pixelclock for the current videomode */
630 	switch (target.space)
631 	{
632 		case B_CMAP8:
633 			max_pclk = si->ps.max_dac1_clock_8;
634 			break;
635 		case B_RGB15_LITTLE:
636 		case B_RGB16_LITTLE:
637 			max_pclk = si->ps.max_dac1_clock_16;
638 			break;
639 		case B_RGB24_LITTLE:
640 			max_pclk = si->ps.max_dac1_clock_24;
641 			break;
642 		case B_RGB32_LITTLE:
643 			max_pclk = si->ps.max_dac1_clock_32;
644 			break;
645 		default:
646 			/* use fail-safe value */
647 			max_pclk = si->ps.max_dac1_clock_32;
648 			break;
649 	}
650 	/* if some dualhead mode is active, an extra restriction might apply */
651 	if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
652 		max_pclk = si->ps.max_dac1_clock_32dh;
653 
654 	/* Make sure the requested pixelclock is within the PLL's operational limits */
655 	/* lower limit is min_pixel_vco divided by highest postscaler-factor */
656 	if (req_pclk < (si->ps.min_pixel_vco / 16.0))
657 	{
658 		LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
659 										req_pclk, (float)(si->ps.min_pixel_vco / 16.0)));
660 		req_pclk = (si->ps.min_pixel_vco / 16.0);
661 	}
662 	/* upper limit is given by pins in combination with current active mode */
663 	if (req_pclk > max_pclk)
664 	{
665 		LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n",
666 														req_pclk, (float)max_pclk));
667 		req_pclk = max_pclk;
668 	}
669 
670 	/* iterate through all valid PLL postscaler settings */
671 	for (p=0x01; p < 0x20; p = p<<1)
672 	{
673 		/* calculate the needed VCO frequency for this postscaler setting */
674 		f_vco = req_pclk * p;
675 
676 		/* check if this is within range of the VCO specs */
677 		if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco))
678 		{
679 			/* iterate trough all valid reference-frequency postscaler settings */
680 			for (m = 2; m <= 32; m++)
681 			{
682 				/* calculate VCO postscaler setting for current setup.. */
683 				n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5);
684 				/* ..and check for validity, BUT:
685 				 * Keep in mind that we need to be able to test n-3 ... n+3! */
686 				if ((n < (8 + 3)) || (n > (128 - 3)))	continue;
687 
688 				/* find error in frequency this setting gives */
689 				error = fabs(req_pclk - ((((si->ps.f_ref * 2)/ m) * n) / p));
690 
691 				/* note the setting if best yet */
692 				if (error < error_best)
693 				{
694 					error_best = error;
695 					best[0]=m;
696 					best[1]=n;
697 					best[2]=p;
698 				}
699 			}
700 		}
701 	}
702 
703 	/* setup the scalers programming values for found optimum setting */
704 	m=best[0] - 1;
705 	n=best[1] - 2;
706 	switch(best[2])
707 	{
708 	case 1:
709 		p = 0x40;
710 		break;
711 	case 2:
712 		p = 0x00;
713 		break;
714 	case 4:
715 		p = 0x01;
716 		break;
717 	case 8:
718 		p = 0x02;
719 		break;
720 	case 16:
721 		p = 0x03;
722 		break;
723 	}
724 
725 	/* log the closest VCO speed found */
726 	f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2);
727 	LOG(2,("DAC: pix VCO frequency found %fMhz\n", f_vco));
728 
729 	/* now find the filtersetting that matches best with this frequency by testing.
730 	 * for now we assume this routine succeeds to get us a stable setting */
731 	if (test)
732 		gx50_dac_check_pix_pll_range(m, n, &p, &q);
733 	else
734 		LOG(2,("DAC: Not testing G450/G550 VCO feedback filters\n"));
735 
736 	/* return the results */
737 	*calc_pclk = f_vco / best[2];
738 	*m_result = m;
739 	*n_result = n;
740 	*p_result = p;
741 
742 	/* display the found pixelclock values */
743 	LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
744 		req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
745 
746 	return B_OK;
747 }
748 
749 /* find nearest valid system PLL setting */
750 static status_t g100_g400max_dac_sys_pll_find(
751 	float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)
752 {
753 	int m = 0, n = 0, p = 0, m_max;
754 	float error, error_best = 999999999;
755 	int best[3];
756 	float f_vco;
757 
758 	/* determine the max. reference-frequency postscaler setting for the
759 	 * current card (see G100, G200 and G400 specs). */
760 	switch(si->ps.card_type)
761 	{
762 	case G100:
763 		LOG(4,("DAC: G100 restrictions apply\n"));
764 		m_max = 7;
765 		break;
766 	case G200:
767 		LOG(4,("DAC: G200 restrictions apply\n"));
768 		m_max = 7;
769 		break;
770 	default:
771 		LOG(4,("DAC: G400/G400MAX restrictions apply\n"));
772 		m_max = 32;
773 		break;
774 	}
775 
776 	/* Make sure the requested systemclock is within the PLL's operational limits */
777 	/* lower limit is min_system_vco divided by highest postscaler-factor */
778 	if (req_sclk < (si->ps.min_system_vco / 8.0))
779 	{
780 		LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
781 										req_sclk, (float)(si->ps.min_system_vco / 8.0)));
782 		req_sclk = (si->ps.min_system_vco / 8.0);
783 	}
784 	/* upper limit is max_system_vco */
785 	if (req_sclk > si->ps.max_system_vco)
786 	{
787 		LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
788 										req_sclk, (float)si->ps.max_system_vco));
789 		req_sclk = si->ps.max_system_vco;
790 	}
791 
792 	/* iterate through all valid PLL postscaler settings */
793 	for (p=0x01; p < 0x10; p = p<<1)
794 	{
795 		/* calculate the needed VCO frequency for this postscaler setting */
796 		f_vco = req_sclk * p;
797 
798 		/* check if this is within range of the VCO specs */
799 		if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco))
800 		{
801 			/* iterate trough all valid reference-frequency postscaler settings */
802 			for (m = 2; m <= m_max; m++)
803 			{
804 				/* calculate VCO postscaler setting for current setup.. */
805 				n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
806 				/* ..and check for validity */
807 				if ((n < 8) || (n > 128))	continue;
808 
809 				/* find error in frequency this setting gives */
810 				error = fabs(req_sclk - (((si->ps.f_ref / m) * n) / p));
811 
812 				/* note the setting if best yet */
813 				if (error < error_best)
814 				{
815 					error_best = error;
816 					best[0]=m;
817 					best[1]=n;
818 					best[2]=p;
819 				}
820 			}
821 		}
822 	}
823 
824 	/* setup the scalers programming values for found optimum setting */
825 	m=best[0] - 1;
826 	n=best[1] - 1;
827 	p=best[2] - 1;
828 
829 	/* calc the needed PLL loopbackfilter setting belonging to current VCO speed,
830 	 * for the current card (see G100, G200 and G400 specs). */
831 	f_vco = (si->ps.f_ref / (m + 1)) * (n + 1);
832 	LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco));
833 
834 	switch(si->ps.card_type)
835 	{
836 	case G100:
837 	case G200:
838 		for(;;)
839 		{
840 			if (f_vco >= 180) {p |= (0x03 << 3); break;};
841 			if (f_vco >= 140) {p |= (0x02 << 3); break;};
842 			if (f_vco >= 100) {p |= (0x01 << 3); break;};
843 			break;
844 		}
845 		break;
846 	default:
847 		for(;;)
848 		{
849 			if (f_vco >= 240) {p |= (0x03 << 3); break;};
850 			if (f_vco >= 170) {p |= (0x02 << 3); break;};
851 			if (f_vco >= 110) {p |= (0x01 << 3); break;};
852 			break;
853 		}
854 		break;
855 	}
856 
857 	/* return the results */
858 	*calc_sclk = f_vco / ((p & 0x07) + 1);
859 	*m_result = m;
860 	*n_result = n;
861 	*p_result = p;
862 
863 	/* display the found pixelclock values */
864 	LOG(2,("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
865 		req_sclk, *calc_sclk, *m_result, *n_result, *p_result));
866 
867 	return B_OK;
868 }
869 
870 static status_t gx50_dac_check_sys_pll(uint8 m, uint8 n, uint8 p)
871 {
872 	uint time = 0, count = 0;
873 
874 	/* program the new clock */
875 	DXIW(SYSPLLM, m);
876 	DXIW(SYSPLLN, n);
877 	DXIW(SYSPLLP, p);
878 
879 	/* Wait for the SYSPLL frequency to lock until timeout occurs */
880 	time = 0;
881 	while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 1000))
882 	{
883 		time++;
884 		snooze(1);
885 	}
886 
887 	/* no lock aquired, not useable */
888 	if (time > 1000) return B_ERROR;
889 
890 	/* check if lock holds for at least 90% of the time */
891 	for (time = 0, count = 0; time <= 1000; time++)
892 	{
893 		if(DXIR(SYSPLLSTAT)&0x40) count++;
894 		snooze(1);
895 	}
896 	/* we have a winner */
897 	if (count >= 900) return B_OK;
898 
899 	/* nogo, the PLL does not stabilize */
900 	return B_ERROR;
901 }
902 
903 static status_t gx50_dac_check_sys_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q)
904 {
905 	uint8 s=0, p_backup = *p;
906 
907 	/* preset no candidate, non working setting */
908 	*q = 0;
909 	/* preset lowest range filter */
910 	*p &= 0x47;
911 
912 	/* iterate through all possible filtersettings */
913 	for (s = 0; s < 8 ;s++)
914 	{
915 		if (gx50_dac_check_sys_pll(m, n, *p)== B_OK)
916 		{
917 			/* now check 3 closest lower and higher settings */
918 			if ((gx50_dac_check_sys_pll(m, n - 3, *p)== B_OK) &&
919 				(gx50_dac_check_sys_pll(m, n - 2, *p)== B_OK) &&
920 				(gx50_dac_check_sys_pll(m, n - 1, *p)== B_OK) &&
921 				(gx50_dac_check_sys_pll(m, n + 1, *p)== B_OK) &&
922 				(gx50_dac_check_sys_pll(m, n + 2, *p)== B_OK) &&
923 				(gx50_dac_check_sys_pll(m, n + 3, *p)== B_OK))
924 			{
925 				LOG(2,("DAC: found optimal working VCO filter: #%d\n",s));
926 				/* preset first choice setting found */
927 				*q = 1;
928 				/* we are done */
929 				return B_OK;
930 			}
931 			else
932 			{
933 				LOG(2,("DAC: found critical but working VCO filter: #%d\n",s));
934 				/* preset backup setting found */
935 				*q = 2;
936 				/* remember this setting */
937 				p_backup = *p;
938 				/* let's continue to see if a better filter exists */
939 			}
940 		}
941 	/* new filtersetting to try */
942 	*p += (1 << 3);
943 	}
944 
945 	/* return the (last found) backup result, or the original p value */
946 	*p = p_backup;
947 	/* we found only a non-optimal value */
948 	if (*q == 2) return B_OK;
949 
950 	/* nothing worked at all */
951 	LOG(2,("DAC: no working VCO filter found!\n"));
952 	return B_ERROR;
953 }
954 
955 /* find nearest valid system PLL setting */
956 static status_t g450_g550_dac_sys_pll_find(
957 	float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result)
958 {
959 	int m = 0, n = 0;
960 	uint8 p = 0, q = 0;
961 	float error, error_best = 999999999;
962 	int best[3];
963 	float f_vco;
964 
965 	LOG(4,("DAC: G450/G550 restrictions apply\n"));
966 
967 	/* Make sure the requested pixelclock is within the PLL's operational limits */
968 	/* lower limit is min_system_vco divided by highest postscaler-factor */
969 	if (req_sclk < (si->ps.min_system_vco / 16.0))
970 	{
971 		LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
972 										req_sclk, (float)(si->ps.min_system_vco / 16.0)));
973 		req_sclk = (si->ps.min_system_vco / 16.0);
974 	}
975 	/* upper limit is max_system_vco */
976 	if (req_sclk > si->ps.max_system_vco)
977 	{
978 		LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n",
979 										req_sclk, (float)si->ps.max_system_vco));
980 		req_sclk = si->ps.max_system_vco;
981 	}
982 
983 	/* iterate through all valid PLL postscaler settings */
984 	for (p=0x01; p < 0x20; p = p<<1)
985 	{
986 		/* calculate the needed VCO frequency for this postscaler setting */
987 		f_vco = req_sclk * p;
988 
989 		/* check if this is within range of the VCO specs */
990 		if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco))
991 		{
992 			/* iterate trough all valid reference-frequency postscaler settings */
993 			for (m = 2; m <= 32; m++)
994 			{
995 				/* calculate VCO postscaler setting for current setup.. */
996 				n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5);
997 				/* ..and check for validity, BUT:
998 				 * Keep in mind that we need to be able to test n-3 ... n+3! */
999 				if ((n < (8 + 3)) || (n > (128 - 3)))	continue;
1000 
1001 				/* find error in frequency this setting gives */
1002 				error = fabs(req_sclk - ((((si->ps.f_ref * 2)/ m) * n) / p));
1003 
1004 				/* note the setting if best yet */
1005 				if (error < error_best)
1006 				{
1007 					error_best = error;
1008 					best[0]=m;
1009 					best[1]=n;
1010 					best[2]=p;
1011 				}
1012 			}
1013 		}
1014 	}
1015 
1016 	/* setup the scalers programming values for found optimum setting */
1017 	m=best[0] - 1;
1018 	n=best[1] - 2;
1019 	switch(best[2])
1020 	{
1021 	case 1:
1022 		p = 0x40;
1023 		break;
1024 	case 2:
1025 		p = 0x00;
1026 		break;
1027 	case 4:
1028 		p = 0x01;
1029 		break;
1030 	case 8:
1031 		p = 0x02;
1032 		break;
1033 	case 16:
1034 		p = 0x03;
1035 		break;
1036 	}
1037 
1038 	/* log the closest VCO speed found */
1039 	f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2);
1040 	LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco));
1041 
1042 	/* now find the filtersetting that matches best with this frequency by testing.
1043 	 * for now we assume this routine succeeds to get us a stable setting */
1044 	gx50_dac_check_sys_pll_range(m, n, &p, &q);
1045 
1046 	/* return the results */
1047 	*calc_sclk = f_vco / best[2];
1048 	*m_result = m;
1049 	*n_result = n;
1050 	*p_result = p;
1051 
1052 	/* display the found pixelclock values */
1053 	LOG(2,("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
1054 		req_sclk, *calc_sclk, *m_result, *n_result, *p_result));
1055 
1056 	return B_OK;
1057 }
1058 
1059 /*set up system pll - NB mclk is memory clock */
1060 status_t g100_dac_set_sys_pll()
1061 {
1062 	/* values for DAC sys pll registers */
1063 	uint8 m, n, p;
1064 	uint time = 0;
1065 	uint32 temp;
1066 	float calc_sclk;
1067 
1068 	LOG(1,("DAC: Setting up G100 system clock\n"));
1069 	g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1070 
1071 	/* reprogram the clock - set PCI/AGP, program, set to programmed */
1072 	/* disable the SYSPLL */
1073 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1074 	/* select the PCI/AGP clock */
1075 	CFGW(OPTION, CFGR(OPTION) & 0xfffffffc);
1076 	/* enable the SYSPLL */
1077 	CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1078 
1079 	/* program the new clock */
1080 	DXIW(SYSPLLM, m);
1081 	DXIW(SYSPLLN, n);
1082 	DXIW(SYSPLLP, p);
1083 
1084 	/* Wait for the SYSPLL frequency to lock until timeout occurs */
1085 	while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1086 	{
1087 		time++;
1088 		snooze(1);
1089 	}
1090 
1091 	if (time > 2000)
1092 		LOG(2,("DAC: sys PLL frequency not locked!\n"));
1093 	else
1094 		LOG(2,("DAC: sys PLL frequency locked\n"));
1095 
1096 	/* disable the SYSPLL */
1097 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1098 	/* setup Gclk, Mclk and FMclk divisors according to PINS */
1099 	temp = (CFGR(OPTION) & 0xffffff27);
1100 	if (si->ps.v3_clk_div & 0x01) temp |= 0x08;
1101 	if (si->ps.v3_clk_div & 0x02) temp |= 0x10;
1102 	if (si->ps.v3_clk_div & 0x04) temp |= 0x80;
1103 	/* fixme: swapPLL can only be done when the rest of the driver respects this also! */
1104 	//never used AFAIK:
1105 	//if (si->ps.v3_clk_div & 0x08) temp |= 0x40;
1106 	/* select the SYSPLL as system clock source */
1107 	temp |= 0x01;
1108 	CFGW(OPTION, temp);
1109 	/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1110 	CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1111 
1112 	return B_OK;
1113 }
1114 
1115 /*set up system pll - NB mclk is memory clock */
1116 status_t g200_dac_set_sys_pll()
1117 {
1118 	/* values for DAC sys pll registers */
1119 	uint8 m, n, p;
1120 	uint time = 0;
1121 	uint32 temp;
1122 	float calc_sclk;
1123 
1124 	LOG(1,("DAC: Setting up G200 system clock\n"));
1125 	g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1126 
1127 	/* reprogram the clock - set PCI/AGP, program, set to programmed */
1128 	/* disable the SYSPLL */
1129 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1130 	/* select the PCI/AGP clock */
1131 	CFGW(OPTION, CFGR(OPTION) & 0xfffffffc);
1132 	/* enable the SYSPLL */
1133 	CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1134 
1135 	/* program the new clock */
1136 	DXIW(SYSPLLM, m);
1137 	DXIW(SYSPLLN, n);
1138 	DXIW(SYSPLLP, p);
1139 
1140 	/* Wait for the SYSPLL frequency to lock until timeout occurs */
1141 	while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1142 	{
1143 		time++;
1144 		snooze(1);
1145 	}
1146 
1147 	if (time > 2000)
1148 		LOG(2,("DAC: sys PLL frequency not locked!\n"));
1149 	else
1150 		LOG(2,("DAC: sys PLL frequency locked\n"));
1151 
1152 	/* disable the SYSPLL */
1153 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1154 	/* setup Wclk divisor and enable/disable Wclk, Gclk and Mclk divisors
1155 	 * according to PINS */
1156 	temp = (CFGR(OPTION2) & 0x00383000);
1157 	if (si->ps.v3_option2_reg & 0x04) temp |= 0x00004000;
1158 	if (si->ps.v3_option2_reg & 0x08) temp |= 0x00008000;
1159 	if (si->ps.v3_option2_reg & 0x10) temp |= 0x00010000;
1160 	if (si->ps.v3_option2_reg & 0x20) temp |= 0x00020000;
1161 	CFGW(OPTION2, temp);
1162 	/* setup Gclk and Mclk divisors according to PINS */
1163 	temp = (CFGR(OPTION) & 0xffffff27);
1164 	if (si->ps.v3_clk_div & 0x01) temp |= 0x08;
1165 	if (si->ps.v3_clk_div & 0x02) temp |= 0x10;
1166 	/* fixme: swapPLL can only be done when the rest of the driver respects this also! */
1167 	//never used AFAIK:
1168 	//if (si->ps.v3_clk_div & 0x08) temp |= 0x40;
1169 	/* select the SYSPLL as system clock source */
1170 	temp |= 0x01;
1171 	CFGW(OPTION, temp);
1172 	/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1173 	CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1174 
1175 	return B_OK;
1176 }
1177 
1178 /*set up system pll - NB mclk is memory clock */
1179 status_t g400_dac_set_sys_pll()
1180 {
1181 	/* values for DAC sys pll registers */
1182 	uint8 m, n, p;
1183 	uint time = 0;
1184 	float calc_sclk;
1185 
1186 	LOG(1,("DAC: Setting up G400/G400MAX system clock\n"));
1187 	g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1188 
1189 	/* reprogram the clock - set PCI/AGP, program, set to programmed */
1190 	/* clear, so don't o/clock addons */
1191 	CFGW(OPTION2, 0);
1192 	/* disable the SYSPLL */
1193 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1194 	/* select the PCI/AGP clock */
1195 	CFGW(OPTION3, 0);
1196 	/* enable the SYSPLL */
1197 	CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1198 
1199 	/* program the new clock */
1200 	DXIW(SYSPLLM, m);
1201 	DXIW(SYSPLLN, n);
1202 	DXIW(SYSPLLP, p);
1203 
1204 	/* Wait for the SYSPLL frequency to lock until timeout occurs */
1205 	while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1206 	{
1207 		time++;
1208 		snooze(1);
1209 	}
1210 
1211 	if (time > 2000)
1212 		LOG(2,("DAC: sys PLL frequency not locked!\n"));
1213 	else
1214 		LOG(2,("DAC: sys PLL frequency locked\n"));
1215 
1216 	/* disable the SYSPLL */
1217 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1218 	/* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */
1219 	CFGW(OPTION3, si->ps.option3_reg);
1220 	/* make sure the PLLs are not swapped (set default config) */
1221 	CFGW(OPTION, CFGR(OPTION) & 0xffffffbf);
1222 	/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1223 	CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1224 
1225 	return B_OK;
1226 }
1227 
1228 /*set up system pll - NB mclk is memory clock */
1229 status_t g450_dac_set_sys_pll()
1230 {
1231 	/* values for DAC sys pll registers */
1232 	uint8 m, n, p;
1233 	uint time = 0;
1234 	float calc_sclk;
1235 
1236 	LOG(1,("DAC: Setting up G450/G550 system clock\n"));
1237 	/* reprogram the clock - set PCI/AGP, program, set to programmed */
1238 	/* clear, so don't o/clock addons */
1239 	CFGW(OPTION2, 0);
1240 	/* setup OPTION via pins */
1241 	CFGW(OPTION, si->ps.option_reg);
1242 	/* disable the SYSPLL */
1243 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1244 	/* select the PCI/AGP clock */
1245 	CFGW(OPTION3, 0);
1246 	/* enable the SYSPLL */
1247 	CFGW(OPTION, CFGR(OPTION) & 0xfffffffb);
1248 
1249 	/* this routine also tests the filters, so it actually programs the clock already */
1250 	g450_g550_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p);
1251 
1252 	/* program the new clock */
1253 	DXIW(SYSPLLM, m);
1254 	DXIW(SYSPLLN, n);
1255 	DXIW(SYSPLLP, p);
1256 
1257 	/* Wait for the SYSPLL frequency to lock until timeout occurs */
1258 	while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000))
1259 	{
1260 		time++;
1261 		snooze(1);
1262 	}
1263 
1264 	if (time > 2000)
1265 		LOG(2,("DAC: sys PLL frequency not locked!\n"));
1266 	else
1267 		LOG(2,("DAC: sys PLL frequency locked\n"));
1268 
1269 	/* disable the SYSPLL */
1270 	CFGW(OPTION, CFGR(OPTION) | 0x04);
1271 	/* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */
1272 	CFGW(OPTION3, si->ps.option3_reg);
1273 	/* setup option2 via pins */
1274 	CFGW(OPTION2, si->ps.option2_reg);
1275 	/* make sure the PLLs are not swapped (set default config) */
1276 	/* fixme: swapPLL can only be done when the rest of the driver respects this also!
1277 	 * (never used AFAIK) */
1278 	CFGW(OPTION, CFGR(OPTION) & 0xffffffbf);
1279 	/* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */
1280 	CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20);
1281 
1282 	return B_OK;
1283 }
1284