1 /* program the DAC */ 2 /* Author: 3 Rudolf Cornelissen 12/2003-5/2004 4 */ 5 6 #define MODULE_BIT 0x00010000 7 8 #include "nv_std.h" 9 10 static status_t nv4_nv10_nv20_dac_pix_pll_find( 11 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test); 12 static status_t g100_g400max_dac_sys_pll_find( 13 float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result); 14 15 /* see if an analog VGA monitor is connected to connector #1 */ 16 bool nv_dac_crt_connected(void) 17 { 18 uint32 output, dac; 19 bool present; 20 21 /* save output connector setting */ 22 output = DACR(OUTPUT); 23 /* save DAC state */ 24 dac = DACR(TSTCTRL); 25 26 /* turn on DAC */ 27 DACW(TSTCTRL, (DACR(TSTCTRL) & 0xfffeffff)); 28 /* select primary head and turn off CRT (and DVI?) outputs */ 29 DACW(OUTPUT, (output & 0x0000feee)); 30 /* wait for signal lines to stabilize */ 31 snooze(1000); 32 /* re-enable CRT output */ 33 DACW(OUTPUT, (DACR(OUTPUT) | 0x00000001)); 34 35 /* setup RGB test signal levels to approx 30% of DAC range and enable them */ 36 DACW(TSTDATA, ((0x2 << 30) | (0x140 << 20) | (0x140 << 10) | (0x140 << 0))); 37 /* route test signals to output */ 38 DACW(TSTCTRL, (DACR(TSTCTRL) | 0x00001000)); 39 /* wait for signal lines to stabilize */ 40 snooze(1000); 41 42 /* do actual detection: all signals paths high == CRT connected */ 43 if (DACR(TSTCTRL) & 0x10000000) 44 { 45 present = true; 46 LOG(4,("DAC: CRT detected on connector #1\n")); 47 } 48 else 49 { 50 present = false; 51 LOG(4,("DAC: no CRT detected on connector #1\n")); 52 } 53 54 /* kill test signal routing */ 55 DACW(TSTCTRL, (DACR(TSTCTRL) & 0xffffefff)); 56 57 /* restore output connector setting */ 58 DACW(OUTPUT, output); 59 /* restore DAC state */ 60 DACW(TSTCTRL, dac); 61 62 return present; 63 } 64 65 /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/ 66 status_t nv_dac_mode(int mode,float brightness) 67 { 68 uint8 *r,*g,*b; 69 int i, ri; 70 71 /*set colour arrays to point to space reserved in shared info*/ 72 r = si->color_data; 73 g = r + 256; 74 b = g + 256; 75 76 LOG(4,("DAC: Setting screen mode %d brightness %f\n", mode, brightness)); 77 /* init the palette for brightness specified */ 78 /* (Nvidia cards always use MSbits from screenbuffer as index for PAL) */ 79 for (i = 0; i < 256; i++) 80 { 81 ri = i * brightness; 82 if (ri > 255) ri = 255; 83 b[i] = g[i] = r[i] = ri; 84 } 85 86 if (nv_dac_palette(r,g,b) != B_OK) return B_ERROR; 87 88 /* disable palette RAM adressing mask */ 89 NV_REG8(NV8_PALMASK) = 0xff; 90 LOG(2,("DAC: PAL pixrdmsk readback $%02x\n", NV_REG8(NV8_PALMASK))); 91 92 return B_OK; 93 } 94 95 /*program the DAC palette using the given r,g,b values*/ 96 status_t nv_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256]) 97 { 98 int i; 99 100 LOG(4,("DAC: setting palette\n")); 101 102 /* select first PAL adress before starting programming */ 103 NV_REG8(NV8_PALINDW) = 0x00; 104 105 /* loop through all 256 to program DAC */ 106 for (i = 0; i < 256; i++) 107 { 108 /* the 6 implemented bits are on b0-b5 of the bus */ 109 NV_REG8(NV8_PALDATA) = r[i]; 110 NV_REG8(NV8_PALDATA) = g[i]; 111 NV_REG8(NV8_PALDATA) = b[i]; 112 } 113 if (NV_REG8(NV8_PALINDW) != 0x00) 114 { 115 LOG(8,("DAC: PAL write index incorrect after programming\n")); 116 return B_ERROR; 117 } 118 if (1) 119 {//reread LUT 120 uint8 R, G, B; 121 122 /* select first PAL adress to read (modulo 3 counter) */ 123 NV_REG8(NV8_PALINDR) = 0x00; 124 for (i = 0; i < 256; i++) 125 { 126 R = NV_REG8(NV8_PALDATA); 127 G = NV_REG8(NV8_PALDATA); 128 B = NV_REG8(NV8_PALDATA); 129 if ((r[i] != R) || (g[i] != G) || (b[i] != B)) 130 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 131 } 132 } 133 134 return B_OK; 135 } 136 137 /*program the pixpll - frequency in kHz*/ 138 status_t nv_dac_set_pix_pll(display_mode target) 139 { 140 uint8 m=0,n=0,p=0; 141 // uint time = 0; 142 143 float pix_setting, req_pclk; 144 status_t result; 145 146 /* fix a DVI or laptop flatpanel to 62Hz refresh! 147 * (we can't risk getting below 60.0Hz as some panels shut-off then!) */ 148 /* Note: 149 * The pixelclock drives the flatpanel modeline, not the CRTC modeline. */ 150 if (si->ps.tmds1_active) 151 { 152 LOG(4,("DAC: Fixing DFP refresh to 62Hz!\n")); 153 154 /* use the panel's modeline to determine the needed pixelclock */ 155 target.timing.pixel_clock = si->ps.p1_timing.pixel_clock; 156 } 157 158 req_pclk = (target.timing.pixel_clock)/1000.0; 159 LOG(4,("DAC: Setting PIX PLL for pixelclock %f\n", req_pclk)); 160 161 /* signal that we actually want to set the mode */ 162 result = nv_dac_pix_pll_find(target,&pix_setting,&m,&n,&p, 1); 163 if (result != B_OK) 164 { 165 return result; 166 } 167 168 /*reprogram (disable,select,wait for stability,enable)*/ 169 // DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0F)|0x04); /*disable the PIXPLL*/ 170 // DXIW(PIXCLKCTRL,(DXIR(PIXCLKCTRL)&0x0C)|0x01); /*select the PIXPLL*/ 171 172 /* program new frequency */ 173 DACW(PIXPLLC, ((p << 16) | (n << 8) | m)); 174 175 /* program 2nd set N and M scalers if they exist (b31=1 enables them) */ 176 if ((si->ps.card_type == NV31) || (si->ps.card_type == NV36)) 177 DACW(PIXPLLC2, 0x80000401); 178 179 /* Wait for the PIXPLL frequency to lock until timeout occurs */ 180 //fixme: do NV cards have a LOCK indication bit?? 181 /* while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 2000)) 182 { 183 time++; 184 snooze(1); 185 } 186 187 if (time > 2000) 188 LOG(2,("DAC: PIX PLL frequency not locked!\n")); 189 else 190 LOG(2,("DAC: PIX PLL frequency locked\n")); 191 DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); //enable the PIXPLL 192 */ 193 194 //for now: 195 /* Give the PIXPLL frequency some time to lock... */ 196 snooze(1000); 197 LOG(2,("DAC: PIX PLL frequency should be locked now...\n")); 198 199 return B_OK; 200 } 201 202 /* find nearest valid pix pll */ 203 status_t nv_dac_pix_pll_find 204 (display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 205 { 206 switch (si->ps.card_type) { 207 default: return nv4_nv10_nv20_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test); 208 } 209 return B_ERROR; 210 } 211 212 /* find nearest valid pixel PLL setting */ 213 static status_t nv4_nv10_nv20_dac_pix_pll_find( 214 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 215 { 216 int m = 0, n = 0, p = 0/*, m_max*/; 217 float error, error_best = 999999999; 218 int best[3]; 219 float f_vco, max_pclk; 220 float req_pclk = target.timing.pixel_clock/1000.0; 221 222 /* determine the max. reference-frequency postscaler setting for the 223 * current card (see G100, G200 and G400 specs). */ 224 /* switch(si->ps.card_type) 225 { 226 case G100: 227 LOG(4,("DAC: G100 restrictions apply\n")); 228 m_max = 7; 229 break; 230 case G200: 231 LOG(4,("DAC: G200 restrictions apply\n")); 232 m_max = 7; 233 break; 234 default: 235 LOG(4,("DAC: G400/G400MAX restrictions apply\n")); 236 m_max = 32; 237 break; 238 } 239 */ 240 LOG(4,("DAC: NV4/NV10/NV20 restrictions apply\n")); 241 242 /* determine the max. pixelclock for the current videomode */ 243 switch (target.space) 244 { 245 case B_CMAP8: 246 max_pclk = si->ps.max_dac1_clock_8; 247 break; 248 case B_RGB15_LITTLE: 249 case B_RGB16_LITTLE: 250 max_pclk = si->ps.max_dac1_clock_16; 251 break; 252 case B_RGB24_LITTLE: 253 max_pclk = si->ps.max_dac1_clock_24; 254 break; 255 case B_RGB32_LITTLE: 256 max_pclk = si->ps.max_dac1_clock_32; 257 break; 258 default: 259 /* use fail-safe value */ 260 max_pclk = si->ps.max_dac1_clock_32; 261 break; 262 } 263 /* if some dualhead mode is active, an extra restriction might apply */ 264 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 265 max_pclk = si->ps.max_dac1_clock_32dh; 266 267 /* Make sure the requested pixelclock is within the PLL's operational limits */ 268 /* lower limit is min_pixel_vco divided by highest postscaler-factor */ 269 if (req_pclk < (si->ps.min_pixel_vco / 16.0)) 270 { 271 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 272 req_pclk, (float)(si->ps.min_pixel_vco / 16.0))); 273 req_pclk = (si->ps.min_pixel_vco / 16.0); 274 } 275 /* upper limit is given by pins in combination with current active mode */ 276 if (req_pclk > max_pclk) 277 { 278 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 279 req_pclk, (float)max_pclk)); 280 req_pclk = max_pclk; 281 } 282 283 /* iterate through all valid PLL postscaler settings */ 284 for (p=0x01; p < 0x20; p = p<<1) 285 { 286 /* calculate the needed VCO frequency for this postscaler setting */ 287 f_vco = req_pclk * p; 288 289 /* check if this is within range of the VCO specs */ 290 if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco)) 291 { 292 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */ 293 if ((si->ps.card_type == NV31) || (si->ps.card_type == NV36)) f_vco /= 4; 294 295 /* iterate trough all valid reference-frequency postscaler settings */ 296 for (m = 7; m <= 14; m++) 297 { 298 /* check if phase-discriminator will be within operational limits */ 299 //fixme: PLL calcs will be resetup/splitup/updated... 300 if (si->ps.card_type == NV36) 301 { 302 if (((si->ps.f_ref / m) < 3.2) || ((si->ps.f_ref / m) > 6.4)) continue; 303 } 304 else 305 { 306 if (((si->ps.f_ref / m) < 1.0) || ((si->ps.f_ref / m) > 2.0)) continue; 307 } 308 309 /* calculate VCO postscaler setting for current setup.. */ 310 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 311 312 /* ..and check for validity */ 313 if ((n < 1) || (n > 255)) continue; 314 315 /* find error in frequency this setting gives */ 316 if ((si->ps.card_type == NV31) || (si->ps.card_type == NV36)) 317 { 318 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */ 319 error = fabs((req_pclk / 4) - (((si->ps.f_ref / m) * n) / p)); 320 } 321 else 322 error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p)); 323 324 /* note the setting if best yet */ 325 if (error < error_best) 326 { 327 error_best = error; 328 best[0]=m; 329 best[1]=n; 330 best[2]=p; 331 } 332 } 333 } 334 } 335 336 /* setup the scalers programming values for found optimum setting */ 337 m = best[0]; 338 n = best[1]; 339 p = best[2]; 340 341 /* log the VCO frequency found */ 342 f_vco = ((si->ps.f_ref / m) * n); 343 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */ 344 if ((si->ps.card_type == NV31) || (si->ps.card_type == NV36)) f_vco *= 4; 345 346 LOG(2,("DAC: pix VCO frequency found %fMhz\n", f_vco)); 347 348 /* return the results */ 349 *calc_pclk = (f_vco / p); 350 *m_result = m; 351 *n_result = n; 352 switch(p) 353 { 354 case 1: 355 p = 0x00; 356 break; 357 case 2: 358 p = 0x01; 359 break; 360 case 4: 361 p = 0x02; 362 break; 363 case 8: 364 p = 0x03; 365 break; 366 case 16: 367 p = 0x04; 368 break; 369 } 370 *p_result = p; 371 372 /* display the found pixelclock values */ 373 LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 374 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 375 376 return B_OK; 377 } 378 379 /* find nearest valid system PLL setting */ 380 static status_t g100_g400max_dac_sys_pll_find( 381 float req_sclk,float * calc_sclk,uint8 * m_result,uint8 * n_result,uint8 * p_result) 382 { 383 int m = 0, n = 0, p = 0, m_max; 384 float error, error_best = 999999999; 385 int best[3]; 386 float f_vco; 387 388 /* determine the max. reference-frequency postscaler setting for the 389 * current card (see G100, G200 and G400 specs). */ 390 switch(si->ps.card_type) 391 { 392 /* case G100: 393 LOG(4,("DAC: G100 restrictions apply\n")); 394 m_max = 7; 395 break; 396 case G200: 397 LOG(4,("DAC: G200 restrictions apply\n")); 398 m_max = 7; 399 break; 400 */ default: 401 LOG(4,("DAC: G400/G400MAX restrictions apply\n")); 402 m_max = 32; 403 break; 404 } 405 406 /* Make sure the requested systemclock is within the PLL's operational limits */ 407 /* lower limit is min_system_vco divided by highest postscaler-factor */ 408 if (req_sclk < (si->ps.min_system_vco / 8.0)) 409 { 410 LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n", 411 req_sclk, (float)(si->ps.min_system_vco / 8.0))); 412 req_sclk = (si->ps.min_system_vco / 8.0); 413 } 414 /* upper limit is max_system_vco */ 415 if (req_sclk > si->ps.max_system_vco) 416 { 417 LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n", 418 req_sclk, (float)si->ps.max_system_vco)); 419 req_sclk = si->ps.max_system_vco; 420 } 421 422 /* iterate through all valid PLL postscaler settings */ 423 for (p=0x01; p < 0x10; p = p<<1) 424 { 425 /* calculate the needed VCO frequency for this postscaler setting */ 426 f_vco = req_sclk * p; 427 428 /* check if this is within range of the VCO specs */ 429 if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco)) 430 { 431 /* iterate trough all valid reference-frequency postscaler settings */ 432 for (m = 2; m <= m_max; m++) 433 { 434 /* calculate VCO postscaler setting for current setup.. */ 435 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 436 /* ..and check for validity */ 437 if ((n < 8) || (n > 128)) continue; 438 439 /* find error in frequency this setting gives */ 440 error = fabs(req_sclk - (((si->ps.f_ref / m) * n) / p)); 441 442 /* note the setting if best yet */ 443 if (error < error_best) 444 { 445 error_best = error; 446 best[0]=m; 447 best[1]=n; 448 best[2]=p; 449 } 450 } 451 } 452 } 453 454 /* setup the scalers programming values for found optimum setting */ 455 m=best[0] - 1; 456 n=best[1] - 1; 457 p=best[2] - 1; 458 459 /* calc the needed PLL loopbackfilter setting belonging to current VCO speed, 460 * for the current card (see G100, G200 and G400 specs). */ 461 f_vco = (si->ps.f_ref / (m + 1)) * (n + 1); 462 LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco)); 463 464 switch(si->ps.card_type) 465 { 466 default: 467 for(;;) 468 { 469 if (f_vco >= 240) {p |= (0x03 << 3); break;}; 470 if (f_vco >= 170) {p |= (0x02 << 3); break;}; 471 if (f_vco >= 110) {p |= (0x01 << 3); break;}; 472 break; 473 } 474 break; 475 } 476 477 /* return the results */ 478 *calc_sclk = f_vco / ((p & 0x07) + 1); 479 *m_result = m; 480 *n_result = n; 481 *p_result = p; 482 483 /* display the found pixelclock values */ 484 LOG(2,("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 485 req_sclk, *calc_sclk, *m_result, *n_result, *p_result)); 486 487 return B_OK; 488 } 489 490 /*set up system pll - NB mclk is memory clock */ 491 status_t g400_dac_set_sys_pll() 492 { 493 /* values for DAC sys pll registers */ 494 uint8 m, n, p; 495 // uint time = 0; 496 float calc_sclk; 497 498 LOG(1,("DAC: Setting up G400/G400MAX system clock\n")); 499 g100_g400max_dac_sys_pll_find((float)si->ps.std_engine_clock, &calc_sclk, &m, &n, &p); 500 501 /* reprogram the clock - set PCI/AGP, program, set to programmed */ 502 /* clear, so don't o/clock addons */ 503 // CFGW(OPTION2, 0); 504 /* disable the SYSPLL */ 505 // CFGW(OPTION, CFGR(OPTION) | 0x04); 506 /* select the PCI/AGP clock */ 507 // CFGW(OPTION3, 0); 508 /* enable the SYSPLL */ 509 // CFGW(OPTION, CFGR(OPTION) & 0xfffffffb); 510 511 /* program the new clock */ 512 // DXIW(SYSPLLM, m); 513 // DXIW(SYSPLLN, n); 514 // DXIW(SYSPLLP, p); 515 516 /* Wait for the SYSPLL frequency to lock until timeout occurs */ 517 /* while((!(DXIR(SYSPLLSTAT)&0x40)) & (time <= 2000)) 518 { 519 time++; 520 snooze(1); 521 } 522 523 if (time > 2000) 524 LOG(2,("DAC: sys PLL frequency not locked!\n")); 525 else 526 LOG(2,("DAC: sys PLL frequency locked\n")); 527 */ 528 /* disable the SYSPLL */ 529 // CFGW(OPTION, CFGR(OPTION) | 0x04); 530 /* setup Gclk, Mclk and Wclk divs via PINS and select SYSPLL as system clock source */ 531 // CFGW(OPTION3, si->ps.option3_reg); 532 /* make sure the PLLs are not swapped (set default config) */ 533 // CFGW(OPTION, CFGR(OPTION) & 0xffffffbf); 534 /* enable the SYSPLL (and make sure the SYSPLL is indeed powered up) */ 535 // CFGW(OPTION, (CFGR(OPTION) & 0xfffffffb) | 0x20); 536 537 return B_OK; 538 } 539