xref: /haiku/src/add-ons/accelerants/matrox/engine/mga_dac.c (revision 4e3137c085bae361922078f123dceb92da700640)
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 
341 /* find nearest valid pixel PLL setting: rewritten by rudolf */
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 */
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 */
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 */
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 
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 
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 */
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 */
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 */
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 */
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 */
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