1 /* program the DAC */ 2 /* Author: 3 Rudolf Cornelissen 12/2003-1/2016 4 */ 5 6 #define MODULE_BIT 0x00010000 7 8 #include "std.h" 9 10 static status_t cle266_km400_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 k8m800_dac_pix_pll_find( 13 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test); 14 15 /* see if an analog VGA monitor is connected to connector #1 */ 16 bool eng_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 eng_dac_mode(int mode,float brightness) 67 { 68 uint8 *r,*g,*b; 69 int i, ri; 70 71 /* 8-bit mode uses the palette differently */ 72 if (mode == BPP8) return B_ERROR; 73 74 /*set colour arrays to point to space reserved in shared info*/ 75 r = si->color_data; 76 g = r + 256; 77 b = g + 256; 78 79 LOG(4,("DAC: Setting screen mode %d brightness %f\n", mode, brightness)); 80 /* init the palette for brightness specified */ 81 /* (Nvidia cards always use MSbits from screenbuffer as index for PAL) */ 82 for (i = 0; i < 256; i++) 83 { 84 ri = i * brightness; 85 if (ri > 255) ri = 255; 86 b[i] = g[i] = r[i] = ri; 87 } 88 89 if (eng_dac_palette(r,g,b) != B_OK) return B_ERROR; 90 91 /* disable palette RAM adressing mask */ 92 ENG_REG8(RG8_PALMASK) = 0xff; 93 LOG(2,("DAC: PAL pixrdmsk readback $%02x\n", ENG_REG8(RG8_PALMASK))); 94 95 return B_OK; 96 } 97 98 /*program the DAC palette using the given r,g,b values*/ 99 status_t eng_dac_palette(uint8 r[256],uint8 g[256],uint8 b[256]) 100 { 101 int i; 102 LOG(4,("DAC: setting palette\n")); 103 104 /* enable primary head palette access */ 105 SEQW(MMIO_EN, ((SEQR(MMIO_EN)) & 0xfe)); 106 /* ??? */ 107 SEQW(0x1b, ((SEQR(0x1b)) | 0x20)); 108 /* disable gamma correction HW mode */ 109 SEQW(FIFOWM, ((SEQR(FIFOWM)) & 0x7f)); 110 /* select first PAL adress before starting programming */ 111 ENG_REG8(RG8_PALINDW) = 0x00; 112 113 /* loop through all 256 to program DAC */ 114 for (i = 0; i < 256; i++) 115 { 116 ENG_REG8(RG8_PALDATA) = r[i]; 117 ENG_REG8(RG8_PALDATA) = g[i]; 118 ENG_REG8(RG8_PALDATA) = b[i]; 119 } 120 if (ENG_REG8(RG8_PALINDW) != 0x00) 121 { 122 LOG(8,("DAC: PAL write index incorrect after programming\n")); 123 return B_ERROR; 124 } 125 if (0) 126 {//reread LUT 127 uint8 R, G, B; 128 129 /* select first PAL adress to read (modulo 3 counter) */ 130 ENG_REG8(RG8_PALINDR) = 0x00; 131 for (i = 0; i < 256; i++) 132 { 133 R = ENG_REG8(RG8_PALDATA); 134 G = ENG_REG8(RG8_PALDATA); 135 B = ENG_REG8(RG8_PALDATA); 136 if ((r[i] != R) || (g[i] != G) || (b[i] != B)) 137 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 138 } 139 } 140 141 return B_OK; 142 } 143 144 /*program the pixpll - frequency in kHz*/ 145 status_t eng_dac_set_pix_pll(display_mode target) 146 { 147 uint8 m=0,n=0,p=0; 148 // uint time = 0; 149 150 float pix_setting, req_pclk; 151 status_t result; 152 153 /* we offer this option because some panels have very tight restrictions, 154 * and there's no overlapping settings range that makes them all work. 155 * note: 156 * this assumes the cards BIOS correctly programmed the panel (is likely) */ 157 //fixme: when VESA DDC EDID stuff is implemented, this option can be deleted... 158 if (0)//si->ps.tmds1_active && !si->settings.pgm_panel) 159 { 160 LOG(4,("DAC: Not programming DFP refresh (specified in via.settings)\n")); 161 return B_OK; 162 } 163 164 /* fix a DVI or laptop flatpanel to 60Hz refresh! */ 165 /* Note: 166 * The pixelclock drives the flatpanel modeline, not the CRTC modeline. */ 167 if (0)//si->ps.tmds1_active) 168 { 169 LOG(4,("DAC: Fixing DFP refresh to 60Hz!\n")); 170 171 /* use the panel's modeline to determine the needed pixelclock */ 172 target.timing.pixel_clock = si->ps.p1_timing.pixel_clock; 173 } 174 175 req_pclk = (target.timing.pixel_clock)/1000.0; 176 LOG(4,("DAC: Setting PIX PLL for pixelclock %f\n", req_pclk)); 177 178 /* signal that we actually want to set the mode */ 179 result = eng_dac_pix_pll_find(target,&pix_setting,&m,&n,&p, 1); 180 if (result != B_OK) 181 { 182 return result; 183 } 184 185 /* reset primary pixelPLL */ 186 SEQW(PLL_RESET, ((SEQR(PLL_RESET)) | 0x02)); 187 snooze(1000); 188 SEQW(PLL_RESET, ((SEQR(PLL_RESET)) & ~0x02)); 189 190 /* program new frequency */ 191 if (si->ps.card_arch != K8M800) 192 { 193 /* fixme: b7 is a lock-indicator or a filter select: to be determined! */ 194 SEQW(PPLL_N_CLE, (n & 0x7f)); 195 SEQW(PPLL_MP_CLE, ((m & 0x3f) | ((p & 0x03) << 6))); 196 } 197 else 198 { 199 /* fixme: preliminary, still needs to be confirmed */ 200 SEQW(PPLL_N_OTH, (n & 0xff)); 201 SEQW(PPLL_M_OTH, (m & 0x1f)); 202 SEQW(PPLL_P_OTH, (p & 0x03) << 2); 203 } 204 205 /* reset primary pixelPLL (playing it safe) */ 206 SEQW(PLL_RESET, ((SEQR(PLL_RESET)) | 0x02)); 207 snooze(1000); 208 SEQW(PLL_RESET, ((SEQR(PLL_RESET)) & ~0x02)); 209 210 /* now select pixelclock source D (the above custom VIA programmable PLL) */ 211 snooze(1000); 212 ENG_REG8(RG8_MISCW) = 0xcf; 213 214 /* Wait for the PIXPLL frequency to lock until timeout occurs */ 215 //fixme: do VIA cards have a LOCK indication bit?? 216 /* while((!(DXIR(PIXPLLSTAT)&0x40)) & (time <= 2000)) 217 { 218 time++; 219 snooze(1); 220 } 221 222 if (time > 2000) 223 LOG(2,("DAC: PIX PLL frequency not locked!\n")); 224 else 225 LOG(2,("DAC: PIX PLL frequency locked\n")); 226 DXIW(PIXCLKCTRL,DXIR(PIXCLKCTRL)&0x0B); //enable the PIXPLL 227 */ 228 229 //for now: 230 /* Give the PIXPLL frequency some time to lock... */ 231 snooze(1000); 232 LOG(2,("DAC: PIX PLL frequency should be locked now...\n")); 233 234 return B_OK; 235 } 236 237 /* find nearest valid pix pll */ 238 status_t eng_dac_pix_pll_find 239 (display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 240 { 241 //fixme: add K8M800 calcs if needed.. 242 switch (si->ps.card_arch) { 243 case K8M800: 244 return k8m800_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test); 245 default: 246 return cle266_km400_dac_pix_pll_find(target, calc_pclk, m_result, n_result, p_result, test); 247 } 248 return B_ERROR; 249 } 250 251 /* find nearest valid pixel PLL setting */ 252 static status_t cle266_km400_dac_pix_pll_find( 253 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 254 { 255 int m = 0, n = 0, p = 0/*, m_max*/; 256 float error, error_best = 999999999; 257 int best[3] = {0}; 258 float f_vco, max_pclk; 259 float req_pclk = target.timing.pixel_clock/1000.0; 260 261 /* determine the max. reference-frequency postscaler setting for the 262 * current card (see G100, G200 and G400 specs). */ 263 /* switch(si->ps.card_type) 264 { 265 case G100: 266 LOG(4,("DAC: G100 restrictions apply\n")); 267 m_max = 7; 268 break; 269 case G200: 270 LOG(4,("DAC: G200 restrictions apply\n")); 271 m_max = 7; 272 break; 273 default: 274 LOG(4,("DAC: G400/G400MAX restrictions apply\n")); 275 m_max = 32; 276 break; 277 } 278 */ 279 LOG(4,("DAC: CLE266/KM400 restrictions apply\n")); 280 281 /* determine the max. pixelclock for the current videomode */ 282 switch (target.space) 283 { 284 case B_CMAP8: 285 max_pclk = si->ps.max_dac1_clock_8; 286 break; 287 case B_RGB15_LITTLE: 288 case B_RGB16_LITTLE: 289 max_pclk = si->ps.max_dac1_clock_16; 290 break; 291 case B_RGB24_LITTLE: 292 max_pclk = si->ps.max_dac1_clock_24; 293 break; 294 case B_RGB32_LITTLE: 295 max_pclk = si->ps.max_dac1_clock_32; 296 break; 297 default: 298 /* use fail-safe value */ 299 max_pclk = si->ps.max_dac1_clock_32; 300 break; 301 } 302 /* if some dualhead mode is active, an extra restriction might apply */ 303 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 304 max_pclk = si->ps.max_dac1_clock_32dh; 305 306 /* Make sure the requested pixelclock is within the PLL's operational limits */ 307 /* lower limit is min_pixel_vco divided by highest postscaler-factor */ 308 if (req_pclk < (si->ps.min_pixel_vco / 8.0)) 309 { 310 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 311 req_pclk, (float)(si->ps.min_pixel_vco / 8.0))); 312 req_pclk = (si->ps.min_pixel_vco / 8.0); 313 } 314 /* upper limit is given by pins in combination with current active mode */ 315 if (req_pclk > max_pclk) 316 { 317 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 318 req_pclk, (float)max_pclk)); 319 req_pclk = max_pclk; 320 } 321 322 /* iterate through all valid PLL postscaler settings */ 323 for (p = 0x01; p < 0x10; p = p << 1) 324 { 325 /* calculate the needed VCO frequency for this postscaler setting */ 326 f_vco = req_pclk * p; 327 328 /* check if this is within range of the VCO specs */ 329 if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco)) 330 { 331 /* iterate trough all valid reference-frequency postscaler settings */ 332 for (m = 1; m <= 63; m++) 333 { 334 /* check if phase-discriminator will be within operational limits */ 335 /* (range as used by VESA BIOS on CLE266, verified.) */ 336 if (((si->ps.f_ref / m) < 2.0) || ((si->ps.f_ref / m) > 3.6)) continue; 337 338 /* calculate VCO postscaler setting for current setup.. */ 339 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 340 341 /* ..and check for validity */ 342 /* (checked VESA BIOS on CLE266, b7 is NOT part of divider.) */ 343 if ((n < 1) || (n > 127)) continue; 344 345 /* find error in frequency this setting gives */ 346 error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p)); 347 348 /* note the setting if best yet */ 349 if (error < error_best) 350 { 351 error_best = error; 352 best[0]=m; 353 best[1]=n; 354 best[2]=p; 355 } 356 } 357 } 358 } 359 360 /* setup the scalers programming values for found optimum setting */ 361 m = best[0]; 362 n = best[1]; 363 p = best[2]; 364 365 /* log the VCO frequency found */ 366 f_vco = ((si->ps.f_ref / m) * n); 367 368 LOG(2,("DAC: pix VCO frequency found %fMhz\n", f_vco)); 369 370 /* return the results */ 371 *calc_pclk = (f_vco / p); 372 *m_result = m; 373 *n_result = n; 374 switch(p) 375 { 376 case 1: 377 p = 0x00; 378 break; 379 case 2: 380 p = 0x01; 381 break; 382 case 4: 383 p = 0x02; 384 break; 385 case 8: 386 p = 0x03; 387 break; 388 } 389 *p_result = p; 390 391 /* display the found pixelclock values */ 392 LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 393 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 394 395 return B_OK; 396 } 397 398 /* find nearest valid pixel PLL setting */ 399 static status_t k8m800_dac_pix_pll_find( 400 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 401 { 402 int m = 0, n = 0, p = 0/*, m_max*/; 403 float error, error_best = 999999999; 404 int best[3] = {0}; 405 float f_vco, max_pclk; 406 float req_pclk = target.timing.pixel_clock/1000.0; 407 408 /* determine the max. reference-frequency postscaler setting for the 409 * current card (see G100, G200 and G400 specs). */ 410 /* switch(si->ps.card_type) 411 { 412 case G100: 413 LOG(4,("DAC: G100 restrictions apply\n")); 414 m_max = 7; 415 break; 416 case G200: 417 LOG(4,("DAC: G200 restrictions apply\n")); 418 m_max = 7; 419 break; 420 default: 421 LOG(4,("DAC: G400/G400MAX restrictions apply\n")); 422 m_max = 32; 423 break; 424 } 425 */ 426 LOG(4,("DAC: K8M800 restrictions apply\n")); 427 428 /* determine the max. pixelclock for the current videomode */ 429 switch (target.space) 430 { 431 case B_CMAP8: 432 max_pclk = si->ps.max_dac1_clock_8; 433 break; 434 case B_RGB15_LITTLE: 435 case B_RGB16_LITTLE: 436 max_pclk = si->ps.max_dac1_clock_16; 437 break; 438 case B_RGB24_LITTLE: 439 max_pclk = si->ps.max_dac1_clock_24; 440 break; 441 case B_RGB32_LITTLE: 442 max_pclk = si->ps.max_dac1_clock_32; 443 break; 444 default: 445 /* use fail-safe value */ 446 max_pclk = si->ps.max_dac1_clock_32; 447 break; 448 } 449 /* if some dualhead mode is active, an extra restriction might apply */ 450 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 451 max_pclk = si->ps.max_dac1_clock_32dh; 452 453 /* Make sure the requested pixelclock is within the PLL's operational limits */ 454 /* lower limit is min_pixel_vco divided by highest postscaler-factor */ 455 if (req_pclk < (si->ps.min_pixel_vco / 8.0)) 456 { 457 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 458 req_pclk, (float)(si->ps.min_pixel_vco / 8.0))); 459 req_pclk = (si->ps.min_pixel_vco / 8.0); 460 } 461 /* upper limit is given by pins in combination with current active mode */ 462 if (req_pclk > max_pclk) 463 { 464 LOG(4,("DAC: clamping pixclock: requested %fMHz, set to %fMHz\n", 465 req_pclk, (float)max_pclk)); 466 req_pclk = max_pclk; 467 } 468 469 /* iterate through all valid PLL postscaler settings */ 470 for (p = 0x01; p < 0x10; p = p << 1) 471 { 472 /* calculate the needed VCO frequency for this postscaler setting */ 473 f_vco = req_pclk * p; 474 475 /* check if this is within range of the VCO specs */ 476 if ((f_vco >= si->ps.min_pixel_vco) && (f_vco <= si->ps.max_pixel_vco)) 477 { 478 /* iterate trough all valid reference-frequency postscaler settings */ 479 /* (checked agains xf86 unichrome driver) */ 480 //fixme: 32 and 33 probably ok as well.. 481 for (m = 2; m <= 31; m++) 482 { 483 /* check if phase-discriminator will be within operational limits */ 484 //fixme: check specs, settings as is now seems safe btw.. 485 if (((si->ps.f_ref / m) < 2.0) || ((si->ps.f_ref / m) > 3.6)) continue; 486 487 /* calculate VCO postscaler setting for current setup.. */ 488 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 489 490 /* ..and check for validity */ 491 /* (checked agains xf86 unichrome driver) */ 492 if ((n < 2) || (n > 257)) continue; 493 494 /* find error in frequency this setting gives */ 495 error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p)); 496 497 /* note the setting if best yet */ 498 if (error < error_best) 499 { 500 error_best = error; 501 best[0]=m; 502 best[1]=n; 503 best[2]=p; 504 } 505 } 506 } 507 } 508 509 /* setup the scalers programming values for found optimum setting */ 510 m = best[0]; 511 n = best[1]; 512 p = best[2]; 513 514 /* log the VCO frequency found */ 515 f_vco = ((si->ps.f_ref / m) * n); 516 517 LOG(2,("DAC: pix VCO frequency found %fMhz\n", f_vco)); 518 519 /* return the results */ 520 *calc_pclk = (f_vco / p); 521 *m_result = m - 2; 522 *n_result = n - 2; 523 switch(p) 524 { 525 case 1: 526 p = 0x00; 527 break; 528 case 2: 529 p = 0x01; 530 break; 531 case 4: 532 p = 0x02; 533 break; 534 case 8: 535 p = 0x03; 536 break; 537 } 538 *p_result = p; 539 540 /* display the found pixelclock values */ 541 LOG(2,("DAC: pix PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 542 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 543 544 return B_OK; 545 } 546 547 /* find nearest valid system PLL setting */ 548 status_t eng_dac_sys_pll_find( 549 float req_sclk, float* calc_sclk, uint8* m_result, uint8* n_result, uint8* p_result, uint8 test) 550 { 551 int m = 0, n = 0, p = 0, m_max, p_max; 552 float error, error_best = 999999999; 553 int best[3] = {0}; 554 float f_vco, discr_low, discr_high; 555 556 /* determine the max. reference-frequency postscaler setting for the 557 * current requested clock */ 558 switch (si->ps.card_arch) 559 { 560 case NV04A: 561 LOG(4,("DAC: NV04 restrictions apply\n")); 562 /* set phase-discriminator frequency range (Mhz) (verified) */ 563 discr_low = 1.0; 564 discr_high = 2.0; 565 /* set max. useable reference frequency postscaler divider factor */ 566 m_max = 14; 567 /* set max. useable VCO output postscaler divider factor */ 568 p_max = 16; 569 break; 570 default: 571 switch (si->ps.card_type) 572 { 573 case NV28: 574 //fixme: how about some other cards??? 575 LOG(4,("DAC: NV28 restrictions apply\n")); 576 /* set max. useable reference frequency postscaler divider factor; 577 * apparantly we would get distortions on high PLL output frequencies if 578 * we use the phase-discriminator at low frequencies */ 579 if (req_sclk > 340.0) m_max = 2; /* Fpll > 340Mhz */ 580 else if (req_sclk > 200.0) m_max = 4; /* 200Mhz < Fpll <= 340Mhz */ 581 else if (req_sclk > 150.0) m_max = 6; /* 150Mhz < Fpll <= 200Mhz */ 582 else m_max = 14; /* Fpll < 150Mhz */ 583 584 /* set max. useable VCO output postscaler divider factor */ 585 p_max = 32; 586 /* set phase-discriminator frequency range (Mhz) (verified) */ 587 discr_low = 1.0; 588 discr_high = 27.0; 589 break; 590 default: 591 LOG(4,("DAC: NV10/NV20/NV30 restrictions apply\n")); 592 /* set max. useable reference frequency postscaler divider factor; 593 * apparantly we would get distortions on high PLL output frequencies if 594 * we use the phase-discriminator at low frequencies */ 595 if (req_sclk > 340.0) m_max = 2; /* Fpll > 340Mhz */ 596 else if (req_sclk > 250.0) m_max = 6; /* 250Mhz < Fpll <= 340Mhz */ 597 else m_max = 14; /* Fpll < 250Mhz */ 598 599 /* set max. useable VCO output postscaler divider factor */ 600 p_max = 16; 601 /* set phase-discriminator frequency range (Mhz) (verified) */ 602 if (si->ps.card_type == NV36) discr_low = 3.2; 603 else discr_low = 1.0; 604 /* (high discriminator spec is failsafe) */ 605 discr_high = 14.0; 606 break; 607 } 608 break; 609 } 610 611 LOG(4,("DAC: PLL reference frequency postscaler divider range is 1 - %d\n", m_max)); 612 LOG(4,("DAC: PLL VCO output postscaler divider range is 1 - %d\n", p_max)); 613 LOG(4,("DAC: PLL discriminator input frequency range is %2.2fMhz - %2.2fMhz\n", 614 discr_low, discr_high)); 615 616 /* Make sure the requested clock is within the PLL's operational limits */ 617 /* lower limit is min_system_vco divided by highest postscaler-factor */ 618 if (req_sclk < (si->ps.min_system_vco / ((float)p_max))) 619 { 620 LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n", 621 req_sclk, (si->ps.min_system_vco / ((float)p_max)))); 622 req_sclk = (si->ps.min_system_vco / ((float)p_max)); 623 } 624 /* upper limit is given by pins */ 625 if (req_sclk > si->ps.max_system_vco) 626 { 627 LOG(4,("DAC: clamping sysclock: requested %fMHz, set to %fMHz\n", 628 req_sclk, (float)si->ps.max_system_vco)); 629 req_sclk = si->ps.max_system_vco; 630 } 631 632 /* iterate through all valid PLL postscaler settings */ 633 for (p=0x01; p <= p_max; p = p<<1) 634 { 635 /* calculate the needed VCO frequency for this postscaler setting */ 636 f_vco = req_sclk * p; 637 638 /* check if this is within range of the VCO specs */ 639 if ((f_vco >= si->ps.min_system_vco) && (f_vco <= si->ps.max_system_vco)) 640 { 641 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */ 642 if (si->ps.ext_pll) f_vco /= 4; 643 644 /* iterate trough all valid reference-frequency postscaler settings */ 645 for (m = 1; m <= m_max; m++) 646 { 647 /* check if phase-discriminator will be within operational limits */ 648 if (((si->ps.f_ref / m) < discr_low) || ((si->ps.f_ref / m) > discr_high)) 649 continue; 650 651 /* calculate VCO postscaler setting for current setup.. */ 652 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 653 654 /* ..and check for validity */ 655 if ((n < 1) || (n > 255)) continue; 656 657 /* find error in frequency this setting gives */ 658 if (si->ps.ext_pll) 659 { 660 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */ 661 error = fabs((req_sclk / 4) - (((si->ps.f_ref / m) * n) / p)); 662 } 663 else 664 error = fabs(req_sclk - (((si->ps.f_ref / m) * n) / p)); 665 666 /* note the setting if best yet */ 667 if (error < error_best) 668 { 669 error_best = error; 670 best[0]=m; 671 best[1]=n; 672 best[2]=p; 673 } 674 } 675 } 676 } 677 678 /* setup the scalers programming values for found optimum setting */ 679 m = best[0]; 680 n = best[1]; 681 p = best[2]; 682 683 /* log the VCO frequency found */ 684 f_vco = ((si->ps.f_ref / m) * n); 685 /* FX5600 and FX5700 tweak for 2nd set N and M scalers */ 686 if (si->ps.ext_pll) f_vco *= 4; 687 688 LOG(2,("DAC: sys VCO frequency found %fMhz\n", f_vco)); 689 690 /* return the results */ 691 *calc_sclk = (f_vco / p); 692 *m_result = m; 693 *n_result = n; 694 switch(p) 695 { 696 case 1: 697 p = 0x00; 698 break; 699 case 2: 700 p = 0x01; 701 break; 702 case 4: 703 p = 0x02; 704 break; 705 case 8: 706 p = 0x03; 707 break; 708 case 16: 709 p = 0x04; 710 break; 711 case 32: 712 p = 0x05; 713 break; 714 } 715 *p_result = p; 716 717 /* display the found pixelclock values */ 718 LOG(2,("DAC: sys PLL check: requested %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 719 req_sclk, *calc_sclk, *m_result, *n_result, *p_result)); 720 721 return B_OK; 722 } 723