xref: /haiku/src/add-ons/accelerants/skeleton/engine/dac2.c (revision bf1feef864e39a6776c4f85ac0f93c13a8921cc4)
168353368SRudolf Cornelissen /* program the secondary DAC */
268353368SRudolf Cornelissen /* Author:
368353368SRudolf Cornelissen    Rudolf Cornelissen 12/2003-9/2004
468353368SRudolf Cornelissen */
568353368SRudolf Cornelissen 
668353368SRudolf Cornelissen #define MODULE_BIT 0x00001000
768353368SRudolf Cornelissen 
8886dbf81SRudolf Cornelissen #include "std.h"
968353368SRudolf Cornelissen 
1068353368SRudolf Cornelissen static status_t nv10_nv20_dac2_pix_pll_find(
1168353368SRudolf Cornelissen 	display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test);
1268353368SRudolf Cornelissen 
1368353368SRudolf Cornelissen /* see if an analog VGA monitor is connected to connector #2 */
eng_dac2_crt_connected()14886dbf81SRudolf Cornelissen bool eng_dac2_crt_connected()
1568353368SRudolf Cornelissen {
1668353368SRudolf Cornelissen 	uint32 output, dac;
1768353368SRudolf Cornelissen 	bool present;
1868353368SRudolf Cornelissen 
1968353368SRudolf Cornelissen 	/* NOTE:
2068353368SRudolf Cornelissen 	 * NV11 can't do this: It will report DAC1 status instead because it HAS no
2168353368SRudolf Cornelissen 	 * actual secondary DAC function. */
2268353368SRudolf Cornelissen 	/* (It DOES have a secondary palette RAM and pixelclock PLL though.) */
2368353368SRudolf Cornelissen 
2468353368SRudolf Cornelissen 	/* save output connector setting */
2568353368SRudolf Cornelissen 	output = DAC2R(OUTPUT);
2668353368SRudolf Cornelissen 	/* save DAC state */
2768353368SRudolf Cornelissen 	dac = DAC2R(TSTCTRL);
2868353368SRudolf Cornelissen 
2968353368SRudolf Cornelissen 	/* turn on DAC2 */
3068353368SRudolf Cornelissen 	DAC2W(TSTCTRL, (DAC2R(TSTCTRL) & 0xfffeffff));
3168353368SRudolf Cornelissen 	/* select primary head and turn off CRT (and DVI?) outputs */
3268353368SRudolf Cornelissen 	DAC2W(OUTPUT, (output & 0x0000feee));
3368353368SRudolf Cornelissen 	/* wait for signal lines to stabilize */
3468353368SRudolf Cornelissen 	snooze(1000);
3568353368SRudolf Cornelissen 	/* re-enable CRT output */
3668353368SRudolf Cornelissen 	DAC2W(OUTPUT, (DAC2R(OUTPUT) | 0x00000001));
3768353368SRudolf Cornelissen 
3868353368SRudolf Cornelissen 	/* setup RGB test signal levels to approx 30% of DAC range and enable them
3968353368SRudolf Cornelissen 	 * (NOTE: testsignal function block resides in DAC1 only (!)) */
4068353368SRudolf Cornelissen 	DACW(TSTDATA, ((0x2 << 30) | (0x140 << 20) | (0x140 << 10) | (0x140 << 0)));
4168353368SRudolf Cornelissen 	/* route test signals to output
4268353368SRudolf Cornelissen 	 * (NOTE: testsignal function block resides in DAC1 only (!)) */
4368353368SRudolf Cornelissen 	DACW(TSTCTRL, (DACR(TSTCTRL) | 0x00001000));
4468353368SRudolf Cornelissen 	/* wait for signal lines to stabilize */
4568353368SRudolf Cornelissen 	snooze(1000);
4668353368SRudolf Cornelissen 
4768353368SRudolf Cornelissen 	/* do actual detection: all signals paths high == CRT connected */
4868353368SRudolf Cornelissen 	if (DAC2R(TSTCTRL) & 0x10000000)
4968353368SRudolf Cornelissen 	{
5068353368SRudolf Cornelissen 		present = true;
5168353368SRudolf Cornelissen 		LOG(4,("DAC2: CRT detected on connector #2\n"));
5268353368SRudolf Cornelissen 	}
5368353368SRudolf Cornelissen 	else
5468353368SRudolf Cornelissen 	{
5568353368SRudolf Cornelissen 		present = false;
5668353368SRudolf Cornelissen 		LOG(4,("DAC2: no CRT detected on connector #2\n"));
5768353368SRudolf Cornelissen 	}
5868353368SRudolf Cornelissen 
5968353368SRudolf Cornelissen 	/* kill test signal routing
6068353368SRudolf Cornelissen 	 * (NOTE: testsignal function block resides in DAC1 only (!)) */
6168353368SRudolf Cornelissen 	DACW(TSTCTRL, (DACR(TSTCTRL) & 0xffffefff));
6268353368SRudolf Cornelissen 
6368353368SRudolf Cornelissen 	/* restore output connector setting */
6468353368SRudolf Cornelissen 	DAC2W(OUTPUT, output);
6568353368SRudolf Cornelissen 	/* restore DAC state */
6668353368SRudolf Cornelissen 	DAC2W(TSTCTRL, dac);
6768353368SRudolf Cornelissen 
6868353368SRudolf Cornelissen 	return present;
6968353368SRudolf Cornelissen }
7068353368SRudolf Cornelissen 
7168353368SRudolf Cornelissen /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/
eng_dac2_mode(int mode,float brightness)72886dbf81SRudolf Cornelissen status_t eng_dac2_mode(int mode,float brightness)
7368353368SRudolf Cornelissen {
7468353368SRudolf Cornelissen 	uint8 *r,*g,*b;
7568353368SRudolf Cornelissen 	int i, ri;
7668353368SRudolf Cornelissen 
7768353368SRudolf Cornelissen 	/*set colour arrays to point to space reserved in shared info*/
7868353368SRudolf Cornelissen 	r = si->color_data;
7968353368SRudolf Cornelissen 	g = r + 256;
8068353368SRudolf Cornelissen 	b = g + 256;
8168353368SRudolf Cornelissen 
8268353368SRudolf Cornelissen 	LOG(4,("DAC2: Setting screen mode %d brightness %f\n", mode, brightness));
8368353368SRudolf Cornelissen 	/* init the palette for brightness specified */
8468353368SRudolf Cornelissen 	/* (Nvidia cards always use MSbits from screenbuffer as index for PAL) */
8568353368SRudolf Cornelissen 	for (i = 0; i < 256; i++)
8668353368SRudolf Cornelissen 	{
8768353368SRudolf Cornelissen 		ri = i * brightness;
8868353368SRudolf Cornelissen 		if (ri > 255) ri = 255;
8968353368SRudolf Cornelissen 		b[i] = g[i] = r[i] = ri;
9068353368SRudolf Cornelissen 	}
9168353368SRudolf Cornelissen 
92886dbf81SRudolf Cornelissen 	if (eng_dac2_palette(r,g,b) != B_OK) return B_ERROR;
9368353368SRudolf Cornelissen 
9468353368SRudolf Cornelissen 	/* disable palette RAM adressing mask */
95*bf1feef8SRudolf Cornelissen 	ENG_REG8(RG8_PAL2MASK) = 0xff;
96*bf1feef8SRudolf Cornelissen 	LOG(2,("DAC2: PAL pixrdmsk readback $%02x\n", ENG_REG8(RG8_PAL2MASK)));
9768353368SRudolf Cornelissen 
9868353368SRudolf Cornelissen 	return B_OK;
9968353368SRudolf Cornelissen }
10068353368SRudolf Cornelissen 
10168353368SRudolf Cornelissen /*program the DAC palette using the given r,g,b values*/
eng_dac2_palette(uint8 r[256],uint8 g[256],uint8 b[256])102886dbf81SRudolf Cornelissen status_t eng_dac2_palette(uint8 r[256],uint8 g[256],uint8 b[256])
10368353368SRudolf Cornelissen {
10468353368SRudolf Cornelissen 	int i;
10568353368SRudolf Cornelissen 
10668353368SRudolf Cornelissen 	LOG(4,("DAC2: setting palette\n"));
10768353368SRudolf Cornelissen 
10868353368SRudolf Cornelissen 	/* select first PAL adress before starting programming */
109*bf1feef8SRudolf Cornelissen 	ENG_REG8(RG8_PAL2INDW) = 0x00;
11068353368SRudolf Cornelissen 
11168353368SRudolf Cornelissen 	/* loop through all 256 to program DAC */
11268353368SRudolf Cornelissen 	for (i = 0; i < 256; i++)
11368353368SRudolf Cornelissen 	{
11468353368SRudolf Cornelissen 		/* the 6 implemented bits are on b0-b5 of the bus */
115*bf1feef8SRudolf Cornelissen 		ENG_REG8(RG8_PAL2DATA) = r[i];
116*bf1feef8SRudolf Cornelissen 		ENG_REG8(RG8_PAL2DATA) = g[i];
117*bf1feef8SRudolf Cornelissen 		ENG_REG8(RG8_PAL2DATA) = b[i];
11868353368SRudolf Cornelissen 	}
119*bf1feef8SRudolf Cornelissen 	if (ENG_REG8(RG8_PAL2INDW) != 0x00)
12068353368SRudolf Cornelissen 	{
12168353368SRudolf Cornelissen 		LOG(8,("DAC2: PAL write index incorrect after programming\n"));
12268353368SRudolf Cornelissen 		return B_ERROR;
12368353368SRudolf Cornelissen 	}
12468353368SRudolf Cornelissen if (1)
12568353368SRudolf Cornelissen  {//reread LUT
12668353368SRudolf Cornelissen 	uint8 R, G, B;
12768353368SRudolf Cornelissen 
12868353368SRudolf Cornelissen 	/* select first PAL adress to read (modulo 3 counter) */
129*bf1feef8SRudolf Cornelissen 	ENG_REG8(RG8_PAL2INDR) = 0x00;
13068353368SRudolf Cornelissen 	for (i = 0; i < 256; i++)
13168353368SRudolf Cornelissen 	{
132*bf1feef8SRudolf Cornelissen 		R = ENG_REG8(RG8_PAL2DATA);
133*bf1feef8SRudolf Cornelissen 		G = ENG_REG8(RG8_PAL2DATA);
134*bf1feef8SRudolf Cornelissen 		B = ENG_REG8(RG8_PAL2DATA);
13568353368SRudolf Cornelissen 		if ((r[i] != R) || (g[i] != G) || (b[i] != B))
13668353368SRudolf Cornelissen 			LOG(1,("DAC2 palette %d: w %x %x %x, r %x %x %x\n", i, r[i], g[i], b[i], R, G, B)); // apsed
13768353368SRudolf Cornelissen 	}
13868353368SRudolf Cornelissen  }
13968353368SRudolf Cornelissen 
14068353368SRudolf Cornelissen 	return B_OK;
14168353368SRudolf Cornelissen }
14268353368SRudolf Cornelissen 
14368353368SRudolf Cornelissen /*program the pixpll - frequency in kHz*/
eng_dac2_set_pix_pll(display_mode target)144886dbf81SRudolf Cornelissen status_t eng_dac2_set_pix_pll(display_mode target)
14568353368SRudolf Cornelissen {
14668353368SRudolf Cornelissen 	uint8 m=0,n=0,p=0;
14768353368SRudolf Cornelissen //	uint time = 0;
14868353368SRudolf Cornelissen 
14968353368SRudolf Cornelissen 	float pix_setting, req_pclk;
15068353368SRudolf Cornelissen 	status_t result;
15168353368SRudolf Cornelissen 
15268353368SRudolf Cornelissen 	/* we offer this option because some panels have very tight restrictions,
15368353368SRudolf Cornelissen 	 * and there's no overlapping settings range that makes them all work.
15468353368SRudolf Cornelissen 	 * note:
15568353368SRudolf Cornelissen 	 * this assumes the cards BIOS correctly programmed the panel (is likely) */
15668353368SRudolf Cornelissen 	//fixme: when VESA DDC EDID stuff is implemented, this option can be deleted...
15768353368SRudolf Cornelissen 	if (si->ps.tmds2_active && !si->settings.pgm_panel)
15868353368SRudolf Cornelissen 	{
1599d063f00SRudolf Cornelissen 		LOG(4,("DAC2: Not programming DFP refresh (specified in skel.settings)\n"));
16068353368SRudolf Cornelissen 		return B_OK;
16168353368SRudolf Cornelissen 	}
16268353368SRudolf Cornelissen 
16368353368SRudolf Cornelissen 	/* fix a DVI or laptop flatpanel to 60Hz refresh! */
16468353368SRudolf Cornelissen 	/* Note:
16568353368SRudolf Cornelissen 	 * The pixelclock drives the flatpanel modeline, not the CRTC modeline. */
16668353368SRudolf Cornelissen 	if (si->ps.tmds2_active)
16768353368SRudolf Cornelissen 	{
16868353368SRudolf Cornelissen 		LOG(4,("DAC2: Fixing DFP refresh to 60Hz!\n"));
16968353368SRudolf Cornelissen 
17068353368SRudolf Cornelissen 		/* use the panel's modeline to determine the needed pixelclock */
17168353368SRudolf Cornelissen 		target.timing.pixel_clock = si->ps.p2_timing.pixel_clock;
17268353368SRudolf Cornelissen 	}
17368353368SRudolf Cornelissen 
17468353368SRudolf Cornelissen 	req_pclk = (target.timing.pixel_clock)/1000.0;
17568353368SRudolf Cornelissen 	LOG(4,("DAC2: Setting PIX PLL for pixelclock %f\n", req_pclk));
17668353368SRudolf Cornelissen 
17768353368SRudolf Cornelissen 	/* signal that we actually want to set the mode */
178886dbf81SRudolf Cornelissen 	result = eng_dac2_pix_pll_find(target,&pix_setting,&m,&n,&p, 1);
17968353368SRudolf Cornelissen 	if (result != B_OK)
18068353368SRudolf Cornelissen 	{
18168353368SRudolf Cornelissen 		return result;
18268353368SRudolf Cornelissen 	}
18368353368SRudolf Cornelissen 
18468353368SRudolf Cornelissen 	/*reprogram (disable,select,wait for stability,enable)*/
18568353368SRudolf Cornelissen //	DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04);  /*disable the PIXPLL*/
18668353368SRudolf Cornelissen //	DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01);  /*select the PIXPLL*/
18768353368SRudolf Cornelissen 
18868353368SRudolf Cornelissen 	/* program new frequency */
18968353368SRudolf Cornelissen 	DAC2W(PIXPLLC, ((p << 16) | (n << 8) | m));
19068353368SRudolf Cornelissen 
19168353368SRudolf Cornelissen 	/* program 2nd set N and M scalers if they exist (b31=1 enables them) */
19268353368SRudolf Cornelissen 	if (si->ps.ext_pll) DAC2W(PIXPLLC2, 0x80000401);
19368353368SRudolf Cornelissen 
19468353368SRudolf Cornelissen 	/* Wait for the PIXPLL frequency to lock until timeout occurs */
19568353368SRudolf Cornelissen //fixme: do NV cards have a LOCK indication bit??
19668353368SRudolf Cornelissen /*	while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 2000))
19768353368SRudolf Cornelissen 	{
19868353368SRudolf Cornelissen 		time++;
19968353368SRudolf Cornelissen 		snooze(1);
20068353368SRudolf Cornelissen 	}
20168353368SRudolf Cornelissen 
20268353368SRudolf Cornelissen 	if (time > 2000)
20368353368SRudolf Cornelissen 		LOG(2,("DAC: PIX PLL frequency not locked!\n"));
20468353368SRudolf Cornelissen 	else
20568353368SRudolf Cornelissen 		LOG(2,("DAC: PIX PLL frequency locked\n"));
20668353368SRudolf Cornelissen 	DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B);         //enable the PIXPLL
20768353368SRudolf Cornelissen */
20868353368SRudolf Cornelissen 
20968353368SRudolf Cornelissen //for now:
21068353368SRudolf Cornelissen 	/* Give the PIXPLL frequency some time to lock... */
21168353368SRudolf Cornelissen 	snooze(1000);
21268353368SRudolf Cornelissen 	LOG(2,("DAC2: PIX PLL frequency should be locked now...\n"));
21368353368SRudolf Cornelissen 
21468353368SRudolf Cornelissen 	return B_OK;
21568353368SRudolf Cornelissen }
21668353368SRudolf Cornelissen 
21768353368SRudolf Cornelissen /* find nearest valid pix pll */
eng_dac2_pix_pll_find(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result,uint8 test)218886dbf81SRudolf Cornelissen status_t eng_dac2_pix_pll_find
21968353368SRudolf Cornelissen 	(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test)
22068353368SRudolf Cornelissen {
22168353368SRudolf Cornelissen 	switch (si->ps.card_type) {
22268353368SRudolf Cornelissen 		default:   return nv10_nv20_dac2_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test);
22368353368SRudolf Cornelissen 	}
22468353368SRudolf Cornelissen 	return B_ERROR;
22568353368SRudolf Cornelissen }
22668353368SRudolf Cornelissen 
22768353368SRudolf Cornelissen /* find nearest valid pixel PLL setting */
nv10_nv20_dac2_pix_pll_find(display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result,uint8 test)22868353368SRudolf Cornelissen static status_t nv10_nv20_dac2_pix_pll_find(
22968353368SRudolf Cornelissen 	display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test)
23068353368SRudolf Cornelissen {
23168353368SRudolf Cornelissen 	int m = 0, n = 0, p = 0/*, m_max*/;
23268353368SRudolf Cornelissen 	float error, error_best = 999999999;
23368353368SRudolf Cornelissen 	int best[3];
23468353368SRudolf Cornelissen 	float f_vco, max_pclk;
23568353368SRudolf Cornelissen 	float req_pclk = target.timing.pixel_clock/1000.0;
23668353368SRudolf Cornelissen 
23768353368SRudolf Cornelissen 	/* determine the max. reference-frequency postscaler setting for the
23868353368SRudolf Cornelissen 	 * current card (see G100, G200 and G400 specs). */
23968353368SRudolf Cornelissen /*	switch(si->ps.card_type)
24068353368SRudolf Cornelissen 	{
24168353368SRudolf Cornelissen 	case G100:
24268353368SRudolf Cornelissen 		LOG(4,("DAC: G100 restrictions apply\n"));
24368353368SRudolf Cornelissen 		m_max = 7;
24468353368SRudolf Cornelissen 		break;
24568353368SRudolf Cornelissen 	case G200:
24668353368SRudolf Cornelissen 		LOG(4,("DAC: G200 restrictions apply\n"));
24768353368SRudolf Cornelissen 		m_max = 7;
24868353368SRudolf Cornelissen 		break;
24968353368SRudolf Cornelissen 	default:
25068353368SRudolf Cornelissen 		LOG(4,("DAC: G400/G400MAX restrictions apply\n"));
25168353368SRudolf Cornelissen 		m_max = 32;
25268353368SRudolf Cornelissen 		break;
25368353368SRudolf Cornelissen 	}
25468353368SRudolf Cornelissen */
25568353368SRudolf Cornelissen 	LOG(4,("DAC2: NV10/NV20 restrictions apply\n"));
25668353368SRudolf Cornelissen 
25768353368SRudolf Cornelissen 	/* determine the max. pixelclock for the current videomode */
25868353368SRudolf Cornelissen 	switch (target.space)
25968353368SRudolf Cornelissen 	{
26068353368SRudolf Cornelissen 		case B_CMAP8:
26168353368SRudolf Cornelissen 			max_pclk = si->ps.max_dac2_clock_8;
26268353368SRudolf Cornelissen 			break;
26368353368SRudolf Cornelissen 		case B_RGB15_LITTLE:
26468353368SRudolf Cornelissen 		case B_RGB16_LITTLE:
26568353368SRudolf Cornelissen 			max_pclk = si->ps.max_dac2_clock_16;
26668353368SRudolf Cornelissen 			break;
26768353368SRudolf Cornelissen 		case B_RGB24_LITTLE:
26868353368SRudolf Cornelissen 			max_pclk = si->ps.max_dac2_clock_24;
26968353368SRudolf Cornelissen 			break;
27068353368SRudolf Cornelissen 		case B_RGB32_LITTLE:
27168353368SRudolf Cornelissen 			max_pclk = si->ps.max_dac2_clock_32;
27268353368SRudolf Cornelissen 			break;
27368353368SRudolf Cornelissen 		default:
27468353368SRudolf Cornelissen 			/* use fail-safe value */
27568353368SRudolf Cornelissen 			max_pclk = si->ps.max_dac2_clock_32;
27668353368SRudolf Cornelissen 			break;
27768353368SRudolf Cornelissen 	}
27868353368SRudolf Cornelissen 	/* if some dualhead mode is active, an extra restriction might apply */
27968353368SRudolf Cornelissen 	if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
28068353368SRudolf Cornelissen 		max_pclk = si->ps.max_dac2_clock_32dh;
28168353368SRudolf Cornelissen 
28268353368SRudolf Cornelissen 	/* Make sure the requested pixelclock is within the PLL's operational limits */
28368353368SRudolf Cornelissen 	/* lower limit is min_pixel_vco divided by highest postscaler-factor */
28468353368SRudolf Cornelissen 	if (req_pclk < (si->ps.min_video_vco / 16.0))
28568353368SRudolf Cornelissen 	{
28668353368SRudolf Cornelissen 		LOG(4,("DAC2: clamping pixclock: requested %fMHz, set to %fMHz\n",
28768353368SRudolf Cornelissen 										req_pclk, (float)(si->ps.min_video_vco / 16.0)));
28868353368SRudolf Cornelissen 		req_pclk = (si->ps.min_video_vco / 16.0);
28968353368SRudolf Cornelissen 	}
29068353368SRudolf Cornelissen 	/* upper limit is given by pins in combination with current active mode */
29168353368SRudolf Cornelissen 	if (req_pclk > max_pclk)
29268353368SRudolf Cornelissen 	{
29368353368SRudolf Cornelissen 		LOG(4,("DAC2: clamping pixclock: requested %fMHz, set to %fMHz\n",
29468353368SRudolf Cornelissen 														req_pclk, (float)max_pclk));
29568353368SRudolf Cornelissen 		req_pclk = max_pclk;
29668353368SRudolf Cornelissen 	}
29768353368SRudolf Cornelissen 
29868353368SRudolf Cornelissen 	/* iterate through all valid PLL postscaler settings */
29968353368SRudolf Cornelissen 	for (p=0x01; p < 0x20; p = p<<1)
30068353368SRudolf Cornelissen 	{
30168353368SRudolf Cornelissen 		/* calculate the needed VCO frequency for this postscaler setting */
30268353368SRudolf Cornelissen 		f_vco = req_pclk * p;
30368353368SRudolf Cornelissen 
30468353368SRudolf Cornelissen 		/* check if this is within range of the VCO specs */
30568353368SRudolf Cornelissen 		if ((f_vco >= si->ps.min_video_vco) && (f_vco <= si->ps.max_video_vco))
30668353368SRudolf Cornelissen 		{
30768353368SRudolf Cornelissen 			/* FX5600 and FX5700 tweak for 2nd set N and M scalers */
30868353368SRudolf Cornelissen 			if (si->ps.ext_pll) f_vco /= 4;
30968353368SRudolf Cornelissen 
31068353368SRudolf Cornelissen 			/* iterate trough all valid reference-frequency postscaler settings */
31168353368SRudolf Cornelissen 			for (m = 7; m <= 14; m++)
31268353368SRudolf Cornelissen 			{
31368353368SRudolf Cornelissen 				/* check if phase-discriminator will be within operational limits */
31468353368SRudolf Cornelissen 				//fixme: PLL calcs will be resetup/splitup/updated...
31568353368SRudolf Cornelissen 				if (si->ps.card_type == NV36)
31668353368SRudolf Cornelissen 				{
31768353368SRudolf Cornelissen 					if (((si->ps.f_ref / m) < 3.2) || ((si->ps.f_ref / m) > 6.4)) continue;
31868353368SRudolf Cornelissen 				}
31968353368SRudolf Cornelissen 				else
32068353368SRudolf Cornelissen 				{
32168353368SRudolf Cornelissen 					if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue;
32268353368SRudolf Cornelissen 				}
32368353368SRudolf Cornelissen 
32468353368SRudolf Cornelissen 				/* calculate VCO postscaler setting for current setup.. */
32568353368SRudolf Cornelissen 				n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5);
32668353368SRudolf Cornelissen 				/* ..and check for validity */
32768353368SRudolf Cornelissen 				if ((n < 1) || (n > 255))	continue;
32868353368SRudolf Cornelissen 
32968353368SRudolf Cornelissen 				/* find error in frequency this setting gives */
33068353368SRudolf Cornelissen 				if (si->ps.ext_pll)
33168353368SRudolf Cornelissen 				{
33268353368SRudolf Cornelissen 					/* FX5600 and FX5700 tweak for 2nd set N and M scalers */
33368353368SRudolf Cornelissen 					error = fabs((req_pclk / 4) - (((si->ps.f_ref / m) * n) / p));
33468353368SRudolf Cornelissen 				}
33568353368SRudolf Cornelissen 				else
33668353368SRudolf Cornelissen 					error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p));
33768353368SRudolf Cornelissen 
33868353368SRudolf Cornelissen 				/* note the setting if best yet */
33968353368SRudolf Cornelissen 				if (error < error_best)
34068353368SRudolf Cornelissen 				{
34168353368SRudolf Cornelissen 					error_best = error;
34268353368SRudolf Cornelissen 					best[0]=m;
34368353368SRudolf Cornelissen 					best[1]=n;
34468353368SRudolf Cornelissen 					best[2]=p;
34568353368SRudolf Cornelissen 				}
34668353368SRudolf Cornelissen 			}
34768353368SRudolf Cornelissen 		}
34868353368SRudolf Cornelissen 	}
34968353368SRudolf Cornelissen 
35068353368SRudolf Cornelissen 	/* setup the scalers programming values for found optimum setting */
35168353368SRudolf Cornelissen 	m = best[0];
35268353368SRudolf Cornelissen 	n = best[1];
35368353368SRudolf Cornelissen 	p = best[2];
35468353368SRudolf Cornelissen 
35568353368SRudolf Cornelissen 	/* log the VCO frequency found */
35668353368SRudolf Cornelissen 	f_vco = ((si->ps.f_ref / m) * n);
35768353368SRudolf Cornelissen 	/* FX5600 and FX5700 tweak for 2nd set N and M scalers */
35868353368SRudolf Cornelissen 	if (si->ps.ext_pll) f_vco *= 4;
35968353368SRudolf Cornelissen 
36068353368SRudolf Cornelissen 	LOG(2,("DAC2: pix VCO frequency found %fMhz\n", f_vco));
36168353368SRudolf Cornelissen 
36268353368SRudolf Cornelissen 	/* return the results */
36368353368SRudolf Cornelissen 	*calc_pclk = (f_vco / p);
36468353368SRudolf Cornelissen 	*m_result = m;
36568353368SRudolf Cornelissen 	*n_result = n;
36668353368SRudolf Cornelissen 	switch(p)
36768353368SRudolf Cornelissen 	{
36868353368SRudolf Cornelissen 	case 1:
36968353368SRudolf Cornelissen 		p = 0x00;
37068353368SRudolf Cornelissen 		break;
37168353368SRudolf Cornelissen 	case 2:
37268353368SRudolf Cornelissen 		p = 0x01;
37368353368SRudolf Cornelissen 		break;
37468353368SRudolf Cornelissen 	case 4:
37568353368SRudolf Cornelissen 		p = 0x02;
37668353368SRudolf Cornelissen 		break;
37768353368SRudolf Cornelissen 	case 8:
37868353368SRudolf Cornelissen 		p = 0x03;
37968353368SRudolf Cornelissen 		break;
38068353368SRudolf Cornelissen 	case 16:
38168353368SRudolf Cornelissen 		p = 0x04;
38268353368SRudolf Cornelissen 		break;
38368353368SRudolf Cornelissen 	}
38468353368SRudolf Cornelissen 	*p_result = p;
38568353368SRudolf Cornelissen 
38668353368SRudolf Cornelissen 	/* display the found pixelclock values */
38768353368SRudolf Cornelissen 	LOG(2,("DAC2: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
38868353368SRudolf Cornelissen 		req_pclk, *calc_pclk, *m_result, *n_result, *p_result));
38968353368SRudolf Cornelissen 
39068353368SRudolf Cornelissen 	return B_OK;
39168353368SRudolf Cornelissen }
392