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/* find nearest valid pixel PLL setting: rewritten by rudolf */
341static 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 */
459static 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 */
617static 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 */
750static 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
870static 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
903static 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 */
956static 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 */
1060status_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 */
1116status_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 */
1179status_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 */
1229status_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