1 /* program the secondary DAC */
3 Rudolf Cornelissen 12/2003-9/2004
6 #define MODULE_BIT 0x00001000
10 static status_t
nv10_nv20_dac2_pix_pll_find(
11 display_mode target
,float * calc_pclk
,uint8
* m_result
,uint8
* n_result
,uint8
* p_result
, uint8 test
);
13 /* see if an analog VGA monitor is connected to connector #2 */
14 bool eng_dac2_crt_connected()
20 * NV11 can't do this: It will report DAC1 status instead because it HAS no
21 * actual secondary DAC function. */
22 /* (It DOES have a secondary palette RAM and pixelclock PLL though.) */
24 /* save output connector setting */
25 output
= DAC2R(OUTPUT
);
30 DAC2W(TSTCTRL
, (DAC2R(TSTCTRL
) & 0xfffeffff));
31 /* select primary head and turn off CRT (and DVI?) outputs */
32 DAC2W(OUTPUT
, (output
& 0x0000feee));
33 /* wait for signal lines to stabilize */
35 /* re-enable CRT output */
36 DAC2W(OUTPUT
, (DAC2R(OUTPUT
) | 0x00000001));
38 /* setup RGB test signal levels to approx 30% of DAC range and enable them
39 * (NOTE: testsignal function block resides in DAC1 only (!)) */
40 DACW(TSTDATA
, ((0x2 << 30) | (0x140 << 20) | (0x140 << 10) | (0x140 << 0)));
41 /* route test signals to output
42 * (NOTE: testsignal function block resides in DAC1 only (!)) */
43 DACW(TSTCTRL
, (DACR(TSTCTRL
) | 0x00001000));
44 /* wait for signal lines to stabilize */
47 /* do actual detection: all signals paths high == CRT connected */
48 if (DAC2R(TSTCTRL
) & 0x10000000)
51 LOG(4,("DAC2: CRT detected on connector #2\n"));
56 LOG(4,("DAC2: no CRT detected on connector #2\n"));
59 /* kill test signal routing
60 * (NOTE: testsignal function block resides in DAC1 only (!)) */
61 DACW(TSTCTRL
, (DACR(TSTCTRL
) & 0xffffefff));
63 /* restore output connector setting */
64 DAC2W(OUTPUT
, output
);
65 /* restore DAC state */
71 /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/
72 status_t
eng_dac2_mode(int mode
,float brightness
)
77 /*set colour arrays to point to space reserved in shared info*/
82 LOG(4,("DAC2: Setting screen mode %d brightness %f\n", mode
, brightness
));
83 /* init the palette for brightness specified */
84 /* (Nvidia cards always use MSbits from screenbuffer as index for PAL) */
85 for (i
= 0; i
< 256; i
++)
88 if (ri
> 255) ri
= 255;
89 b
[i
] = g
[i
] = r
[i
] = ri
;
92 if (eng_dac2_palette(r
,g
,b
) != B_OK
) return B_ERROR
;
94 /* disable palette RAM adressing mask */
95 ENG_REG8(RG8_PAL2MASK
) = 0xff;
96 LOG(2,("DAC2: PAL pixrdmsk readback $%02x\n", ENG_REG8(RG8_PAL2MASK
)));
101 /*program the DAC palette using the given r,g,b values*/
102 status_t
eng_dac2_palette(uint8 r
[256],uint8 g
[256],uint8 b
[256])
106 LOG(4,("DAC2: setting palette\n"));
108 /* select first PAL adress before starting programming */
109 ENG_REG8(RG8_PAL2INDW
) = 0x00;
111 /* loop through all 256 to program DAC */
112 for (i
= 0; i
< 256; i
++)
114 /* the 6 implemented bits are on b0-b5 of the bus */
115 ENG_REG8(RG8_PAL2DATA
) = r
[i
];
116 ENG_REG8(RG8_PAL2DATA
) = g
[i
];
117 ENG_REG8(RG8_PAL2DATA
) = b
[i
];
119 if (ENG_REG8(RG8_PAL2INDW
) != 0x00)
121 LOG(8,("DAC2: PAL write index incorrect after programming\n"));
128 /* select first PAL adress to read (modulo 3 counter) */
129 ENG_REG8(RG8_PAL2INDR
) = 0x00;
130 for (i
= 0; i
< 256; i
++)
132 R
= ENG_REG8(RG8_PAL2DATA
);
133 G
= ENG_REG8(RG8_PAL2DATA
);
134 B
= ENG_REG8(RG8_PAL2DATA
);
135 if ((r
[i
] != R
) || (g
[i
] != G
) || (b
[i
] != B
))
136 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
143 /*program the pixpll - frequency in kHz*/
144 status_t
eng_dac2_set_pix_pll(display_mode target
)
149 float pix_setting
, req_pclk
;
152 /* we offer this option because some panels have very tight restrictions,
153 * and there's no overlapping settings range that makes them all work.
155 * this assumes the cards BIOS correctly programmed the panel (is likely) */
156 //fixme: when VESA DDC EDID stuff is implemented, this option can be deleted...
157 if (si
->ps
.tmds2_active
&& !si
->settings
.pgm_panel
)
159 LOG(4,("DAC2: Not programming DFP refresh (specified in skel.settings)\n"));
163 /* fix a DVI or laptop flatpanel to 60Hz refresh! */
165 * The pixelclock drives the flatpanel modeline, not the CRTC modeline. */
166 if (si
->ps
.tmds2_active
)
168 LOG(4,("DAC2: Fixing DFP refresh to 60Hz!\n"));
170 /* use the panel's modeline to determine the needed pixelclock */
171 target
.timing
.pixel_clock
= si
->ps
.p2_timing
.pixel_clock
;
174 req_pclk
= (target
.timing
.pixel_clock
)/1000.0;
175 LOG(4,("DAC2: Setting PIX PLL for pixelclock %f\n", req_pclk
));
177 /* signal that we actually want to set the mode */
178 result
= eng_dac2_pix_pll_find(target
,&pix_setting
,&m
,&n
,&p
, 1);
184 /*reprogram (disable,select,wait for stability,enable)*/
185 // DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/
186 // DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/
188 /* program new frequency */
189 DAC2W(PIXPLLC
, ((p
<< 16) | (n
<< 8) | m
));
191 /* program 2nd set N and M scalers if they exist (b31=1 enables them) */
192 if (si
->ps
.ext_pll
) DAC2W(PIXPLLC2
, 0x80000401);
194 /* Wait for the PIXPLL frequency to lock until timeout occurs */
195 //fixme: do NV cards have a LOCK indication bit??
196 /* while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 2000))
203 LOG(2,("DAC: PIX PLL frequency not locked!\n"));
205 LOG(2,("DAC: PIX PLL frequency locked\n"));
206 DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); //enable the PIXPLL
210 /* Give the PIXPLL frequency some time to lock... */
212 LOG(2,("DAC2: PIX PLL frequency should be locked now...\n"));
217 /* find nearest valid pix pll */
218 status_t eng_dac2_pix_pll_find
219 (display_mode target
,float * calc_pclk
,uint8
* m_result
,uint8
* n_result
,uint8
* p_result
, uint8 test
)
221 switch (si
->ps
.card_type
) {
222 default: return nv10_nv20_dac2_pix_pll_find(target
, calc_pclk
, m_result
, n_result
, p_result
, test
);
227 /* find nearest valid pixel PLL setting */
228 static status_t
nv10_nv20_dac2_pix_pll_find(
229 display_mode target
,float * calc_pclk
,uint8
* m_result
,uint8
* n_result
,uint8
* p_result
, uint8 test
)
231 int m
= 0, n
= 0, p
= 0/*, m_max*/;
232 float error
, error_best
= 999999999;
234 float f_vco
, max_pclk
;
235 float req_pclk
= target
.timing
.pixel_clock
/1000.0;
237 /* determine the max. reference-frequency postscaler setting for the
238 * current card (see G100, G200 and G400 specs). */
239 /* switch(si->ps.card_type)
242 LOG(4,("DAC: G100 restrictions apply\n"));
246 LOG(4,("DAC: G200 restrictions apply\n"));
250 LOG(4,("DAC: G400/G400MAX restrictions apply\n"));
255 LOG(4,("DAC2: NV10/NV20 restrictions apply\n"));
257 /* determine the max. pixelclock for the current videomode */
258 switch (target
.space
)
261 max_pclk
= si
->ps
.max_dac2_clock_8
;
265 max_pclk
= si
->ps
.max_dac2_clock_16
;
268 max_pclk
= si
->ps
.max_dac2_clock_24
;
271 max_pclk
= si
->ps
.max_dac2_clock_32
;
274 /* use fail-safe value */
275 max_pclk
= si
->ps
.max_dac2_clock_32
;
278 /* if some dualhead mode is active, an extra restriction might apply */
279 if ((target
.flags
& DUALHEAD_BITS
) && (target
.space
== B_RGB32_LITTLE
))
280 max_pclk
= si
->ps
.max_dac2_clock_32dh
;
282 /* Make sure the requested pixelclock is within the PLL's operational limits */
283 /* lower limit is min_pixel_vco divided by highest postscaler-factor */
284 if (req_pclk
< (si
->ps
.min_video_vco
/ 16.0))
286 LOG(4,("DAC2: clamping pixclock: requested %fMHz, set to %fMHz\n",
287 req_pclk
, (float)(si
->ps
.min_video_vco
/ 16.0)));
288 req_pclk
= (si
->ps
.min_video_vco
/ 16.0);
290 /* upper limit is given by pins in combination with current active mode */
291 if (req_pclk
> max_pclk
)
293 LOG(4,("DAC2: clamping pixclock: requested %fMHz, set to %fMHz\n",
294 req_pclk
, (float)max_pclk
));
298 /* iterate through all valid PLL postscaler settings */
299 for (p
=0x01; p
< 0x20; p
= p
<<1)
301 /* calculate the needed VCO frequency for this postscaler setting */
302 f_vco
= req_pclk
* p
;
304 /* check if this is within range of the VCO specs */
305 if ((f_vco
>= si
->ps
.min_video_vco
) && (f_vco
<= si
->ps
.max_video_vco
))
307 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */
308 if (si
->ps
.ext_pll
) f_vco
/= 4;
310 /* iterate trough all valid reference-frequency postscaler settings */
311 for (m
= 7; m
<= 14; m
++)
313 /* check if phase-discriminator will be within operational limits */
314 //fixme: PLL calcs will be resetup/splitup/updated...
315 if (si
->ps
.card_type
== NV36
)
317 if (((si
->ps
.f_ref
/ m
) < 3.2) || ((si
->ps
.f_ref
/ m
) > 6.4)) continue;
321 if (((si
->ps
.f_ref
/ m
) < 1.0) || ((si
->ps
.f_ref
/ m
) > 2.0)) continue;
324 /* calculate VCO postscaler setting for current setup.. */
325 n
= (int)(((f_vco
* m
) / si
->ps
.f_ref
) + 0.5);
326 /* ..and check for validity */
327 if ((n
< 1) || (n
> 255)) continue;
329 /* find error in frequency this setting gives */
332 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */
333 error
= fabs((req_pclk
/ 4) - (((si
->ps
.f_ref
/ m
) * n
) / p
));
336 error
= fabs(req_pclk
- (((si
->ps
.f_ref
/ m
) * n
) / p
));
338 /* note the setting if best yet */
339 if (error
< error_best
)
350 /* setup the scalers programming values for found optimum setting */
355 /* log the VCO frequency found */
356 f_vco
= ((si
->ps
.f_ref
/ m
) * n
);
357 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */
358 if (si
->ps
.ext_pll
) f_vco
*= 4;
360 LOG(2,("DAC2: pix VCO frequency found %fMhz\n", f_vco
));
362 /* return the results */
363 *calc_pclk
= (f_vco
/ p
);
386 /* display the found pixelclock values */
387 LOG(2,("DAC2: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
388 req_pclk
, *calc_pclk
, *m_result
, *n_result
, *p_result
));