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
12static status_t milx_dac_pix_pll_find(
13	display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
14static 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);
16static 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);
18static status_t g100_g400max_dac_sys_pll_find(
19	float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result);
20static 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)*/
24status_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*/
146status_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	}
167if (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 */
193status_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
235static 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
270static 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 */
327status_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 */
342static 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 */
462static 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 */
622static 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 */
757static 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
879static 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
912static 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 */
966static 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 */
1071status_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 */
1127status_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 */
1190status_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 */
1240status_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