1 /* program the MAVEN in monitor mode */ 2 3 /* Authors: 4 Mark Watson 6/2000, 5 Rudolf Cornelissen 1/2003-5/2006 6 7 Thanx to Petr Vandrovec for writing matroxfb. 8 */ 9 10 #define MODULE_BIT 0x00001000 11 12 #include "mga_std.h" 13 14 status_t g450_g550_maven_set_vid_pll(display_mode target); 15 status_t g100_g400max_maven_set_vid_pll(display_mode target); 16 17 /* This routine blanks the first 'line' below the screen used if there's memory left 18 * to place it in. This will prevent overscanning rubbish on the MAVEN DAC, but only 19 * if no screen using virtual height is setup. 20 * In the rare event the mode and overlay use up so much RAM there's not enough room 21 * left for one blank line, you will get overscanning rubbish from the overlay as it 22 * will overwrite the blank line placed here. 23 * This 'rectangle fill' is done in software because not all modes are supported by 24 * the acc engine. 25 * This function exists to partly overcome a G400 MAVEN hardware design fault, which 26 * influences output in both monitor and TVout modes. The fault is that the MAVEN 27 * keeps repeatedly displaying the last 8 pixels fetched from memory until fetching 28 * restarts after a vertical retrace. 29 * In order to let the maven fetch black pixels, an extra line has to be added to its 30 * CRTC timing. This line needs to be entirely filled black, so with zeros. This line 31 * will be displayed as last visible line, and the last 8 pixels of it will be 32 * repeated during vertical retrace. 33 * Note that the overscanning rubbish can be suppressed in TVout modes by extending 34 * the vertical sync pulse all the way 'to the end'. */ 35 status_t gx00_maven_clrline() 36 { 37 uint32 x, screensize, pointer_reservation; 38 uint8* adr; 39 40 /* this function is nolonger needed on G450/G550 cards */ 41 if (si->ps.card_type > G400MAX) return B_OK; 42 43 /* checkout space needed for hardcursor (if any) */ 44 pointer_reservation = 0; 45 /* MIL 1/2 cards have a seperate buffer for the cursorbitmap inside the DAC */ 46 if ((si->ps.card_type >= G100) && si->settings.hardcursor) pointer_reservation = 1024; 47 48 /* calculate actual screensize */ 49 screensize = si->fbc.bytes_per_row * si->dm.virtual_height; 50 51 /* check if there's room left for a full blank line following the actual screen */ 52 if ((screensize + si->fbc.bytes_per_row + pointer_reservation) <= 53 (si->ps.memory_size * 1024 * 1024)) 54 { 55 LOG(4,("MAVEN: clearing line directly below screen\n")); 56 57 /* calculate first adress beyond actual screen */ 58 adr = (uint8*)si->fbc.frame_buffer; 59 adr += screensize; 60 /* clear the line */ 61 for (x = 0; x < si->fbc.bytes_per_row; x++) 62 { 63 *(adr + x) = 0x00; 64 } 65 } 66 else 67 LOG(4,("MAVEN: not clearing line directly below screen: no memory left\n")); 68 69 return B_OK; 70 } 71 72 status_t gx00_maven_dpms(bool display, bool h, bool v) 73 { 74 /* this function is nolonger needed on G450/G550 cards */ 75 if (si->ps.card_type > G400MAX) return B_OK; 76 77 if (display && h && v) 78 { 79 /* turn on screen */ 80 if (!(si->dm.flags & TV_BITS)) 81 { 82 /* monitor mode */ 83 MAVW(MONEN, 0xb2); 84 MAVW(MONSET, 0x20); /* must be set to this in monitor mode */ 85 MAVW(OUTMODE, 0x03); /* output: monitor mode */ 86 MAVW(STABLE, 0x22); /* makes picture stable? */ 87 MAVW(TEST, 0x00); /* turn off test signal */ 88 } 89 else 90 { 91 /* TVout mode */ 92 MAVW(MONEN, 0xb3); 93 MAVW(MONSET, 0x20); 94 MAVW(OUTMODE, 0x08); /* output: SVideo/Composite */ 95 MAVW(STABLE, 0x02); /* makes picture stable? */ 96 //fixme? linux uses 0x14... 97 MAVW(TEST, (MAVR(TEST) & 0x10)); 98 } 99 } 100 else 101 { 102 /* turn off screen using a few methods! */ 103 MAVW(STABLE, 0x6a); 104 MAVW(OUTMODE, 0x00); 105 } 106 107 return B_OK; 108 } 109 110 /*set a mode line - inputs are in pixels/scanlines*/ 111 status_t gx00_maven_set_timing(display_mode target) 112 { 113 uint8 temp, cnt, offset, loop; 114 115 /* this function is nolonger needed on G450/G550 cards */ 116 if (si->ps.card_type > G400MAX) return B_OK; 117 118 LOG(4,("MAVEN: setting timing\n")); 119 120 /*check horizontal timing parameters are to nearest 8 pixels*/ 121 if ((target.timing.h_display & 0x07) | 122 (target.timing.h_sync_start & 0x07) | 123 (target.timing.h_sync_end & 0x07) | 124 (target.timing.h_total & 0x07)) 125 { 126 LOG(8,("MAVEN: Horizontal timing is not multiples of 8 pixels\n")); 127 return B_ERROR; 128 } 129 130 /*program the MAVEN*/ 131 MAVWW(LASTLINEL, target.timing.h_total); 132 MAVWW(HSYNCLENL, (target.timing.h_sync_end - target.timing.h_sync_start)); 133 MAVWW(HSYNCSTRL, (target.timing.h_total - target.timing.h_sync_start)); 134 MAVWW(HDISPLAYL, ((target.timing.h_total - target.timing.h_sync_start) + 135 target.timing.h_display)); 136 MAVWW(HTOTALL, (target.timing.h_total + 1)); 137 138 MAVWW(VSYNCLENL, (target.timing.v_sync_end - target.timing.v_sync_start - 1)); 139 MAVWW(VSYNCSTRL, (target.timing.v_total - target.timing.v_sync_start)); 140 MAVWW(VDISPLAYL, (target.timing.v_total - 1)); 141 MAVWW(VTOTALL, (target.timing.v_total - 1)); 142 143 MAVWW(HVIDRSTL, (target.timing.h_total - si->crtc_delay)); 144 MAVWW(VVIDRSTL, (target.timing.v_total - 2)); 145 146 /* setup HSYNC & VSYNC polarity */ 147 LOG(2,("MAVEN: sync polarity: ")); 148 temp = MAVR(LUMA); 149 150 /* find out which offset from the 'reset position' we need */ 151 switch (((target.timing.flags & B_POSITIVE_HSYNC) >> (29 - 0)) | 152 ((target.timing.flags & B_POSITIVE_VSYNC) >> (30 - 1))) 153 { 154 case 0: 155 /* H neg, V neg */ 156 LOG(2,("H:neg V:neg\n")); 157 offset = 2; 158 break; 159 case 1: 160 /* H pos, V neg */ 161 LOG(2,("H:pos V:neg\n")); 162 offset = 3; 163 break; 164 case 2: 165 /* H neg, V pos */ 166 LOG(2,("H:neg V:pos\n")); 167 offset = 1; 168 break; 169 case 3: 170 default: 171 /* H pos, V pos */ 172 LOG(2,("H:pos V:pos\n")); 173 offset = 0; 174 break; 175 } 176 /* calculate the number of steps we need to make from the current 'position' */ 177 cnt = 0; 178 if ((offset - ((int)si->maven_syncpol_offset)) < 0) cnt = 4; 179 cnt += offset - si->maven_syncpol_offset; 180 /* note the offset from 'reset position' we will have now */ 181 si->maven_syncpol_offset = offset; 182 183 /* program the maven: */ 184 /* make sure pulse bit is reset */ 185 temp &= ~0x20; 186 MAVW(LUMA, temp); 187 snooze(5); 188 /* enable maven sync polarity programming */ 189 temp |= 0x10; 190 MAVW(LUMA, temp); 191 snooze(5); 192 /* pulse sync programming bit until we have the polarities we want */ 193 for (loop = 0; loop < cnt; loop++) 194 { 195 MAVW(LUMA, (temp | 0x20)); 196 snooze(5); 197 MAVW(LUMA, (temp & ~0x20)); 198 snooze(5); 199 } 200 /* disable maven sync polarity programming and reset pulse bit */ 201 MAVW(LUMA, (temp & ~0x30)); 202 203 return B_OK; 204 } 205 206 /*set the mode, brightness is a value from 0->2 (where 1 is equivalent to direct)*/ 207 status_t gx00_maven_mode(int mode,float brightness) 208 { 209 uint8 luma; 210 211 /* this function is nolonger needed on G450/G550 cards */ 212 if (si->ps.card_type > G400MAX) return B_OK; 213 214 /* set luma to a suitable value for brightness */ 215 /* assuming 0x0a is a sensible value */ 216 /* fixme: 217 * it looks like b6 and/or b7 determine the luma: just two values possible. */ 218 /* NOTE: b4 and b5 have another function, don't set! (sync polarity programming) */ 219 luma = (uint8)(0x0a * brightness); 220 if (luma > 0x0f) luma = 0x0f; 221 222 MAVW(LUMA, luma); 223 LOG(4,("MAVEN: LUMA setting - %x\n", luma)); 224 225 return B_OK; 226 } 227 228 void gx00_maven_shutoff() 229 { 230 switch (si->ps.card_type) 231 { 232 case G100: 233 case G200: 234 //fixme: see if this works on G400 too: 235 //case G400: 236 //case G400MAX: 237 /* prevents distortions on CRTC1... */ 238 MAVW(TEST, 0x03); 239 MAVW(MONEN, 0x00); 240 MAVW(MONSET, 0x00); 241 break; 242 default: 243 break; 244 } 245 } 246 247 status_t gx00_maven_set_vid_pll(display_mode target) 248 { 249 switch (si->ps.card_type) 250 { 251 case G450: 252 case G550: 253 return g450_g550_maven_set_vid_pll(target); 254 break; 255 default: 256 return g100_g400max_maven_set_vid_pll(target); 257 break; 258 } 259 return B_ERROR; 260 } 261 262 status_t g450_g550_maven_set_vid_pll(display_mode target) 263 { 264 uint8 m=0,n=0,p=0; 265 uint time = 0; 266 267 float pix_setting, req_pclk; 268 status_t result; 269 270 req_pclk = (target.timing.pixel_clock)/1000.0; 271 LOG(4,("MAVEN: Setting VID PLL for pixelclock %f\n", req_pclk)); 272 273 result = g450_g550_maven_vid_pll_find(target,&pix_setting,&m,&n,&p, 1); 274 if (result != B_OK) 275 { 276 return result; 277 } 278 279 /*reprogram (disable,select,wait for stability,enable)*/ 280 CR2W(CTL, (CR2R(CTL) | 0x08)); /* disable the VIDPLL */ 281 CR2W(CTL, (CR2R(CTL) | 0x06)); /* select the VIDPLL */ 282 DXIW(VIDPLLM,(m)); /* set m value */ 283 DXIW(VIDPLLN,(n)); /* set n value */ 284 DXIW(VIDPLLP,(p)); /* set p value */ 285 286 /* Wait for the VIDPLL frequency to lock until timeout occurs */ 287 while((!(DXIR(VIDPLLSTAT) & 0x40)) & (time <= 2000)) 288 { 289 time++; 290 snooze(1); 291 } 292 293 if (time > 2000) 294 LOG(2,("MAVEN: VID PLL frequency not locked!\n")); 295 else 296 LOG(2,("MAVEN: VID PLL frequency locked\n")); 297 CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */ 298 299 return B_OK; 300 } 301 302 /* program the video PLL in the MAVEN */ 303 status_t g100_g400max_maven_set_vid_pll(display_mode target) 304 { 305 uint8 m=0,n=0,p=0; 306 307 float pix_setting, req_pclk; 308 status_t result; 309 310 req_pclk = (target.timing.pixel_clock)/1000.0; 311 LOG(4,("MAVEN: Setting VID PLL for pixelclock %f\n", req_pclk)); 312 313 result = g100_g400max_maven_vid_pll_find(target,&pix_setting,&m,&n,&p); 314 if (result != B_OK) 315 { 316 return result; 317 } 318 319 /*reprogram (select,wait for stability)*/ 320 MAVW(PIXPLLM,(m)); /* set m value */ 321 MAVW(PIXPLLN,(n)); /* set n value */ 322 MAVW(PIXPLLP,(p | 0x80)); /* set p value enabling PLL */ 323 324 /* Wait for the VIDPLL frequency to lock: detection is not possible it seems */ 325 snooze(2000); 326 327 LOG(2,("MAVEN: VID PLL frequency should be locked now...\n")); 328 329 return B_OK; 330 } 331 332 333 /* find nearest valid video PLL setting */ 334 status_t g100_g400max_maven_vid_pll_find( 335 display_mode target, float* calc_pclk, uint8* m_result, uint8* n_result, 336 uint8* p_result) 337 { 338 int m = 0, n = 0, p = 0, m_max; 339 float error, error_best = INT_MAX; 340 int best[3] = {0, 0, 0}; 341 float f_vco, max_pclk; 342 float req_pclk = target.timing.pixel_clock/1000.0; 343 344 /* determine the max. reference-frequency postscaler setting for the current card */ 345 //fixme: check G100 and G200 m_max if possible... 346 switch (si->ps.card_type) 347 { 348 case G100: 349 LOG(4, ("MAVEN: G100 restrictions apply\n")); 350 m_max = 32; 351 break; 352 case G200: 353 LOG(4, ("MAVEN: G200 restrictions apply\n")); 354 m_max = 32; 355 break; 356 default: 357 LOG(4, ("MAVEN: G400/G400MAX restrictions apply\n")); 358 m_max = 32; 359 break; 360 } 361 362 /* determine the max. pixelclock for the current videomode */ 363 switch (target.space) 364 { 365 case B_RGB16_LITTLE: 366 max_pclk = si->ps.max_dac2_clock_16; 367 break; 368 case B_RGB32_LITTLE: 369 max_pclk = si->ps.max_dac2_clock_32; 370 break; 371 default: 372 /* use fail-safe value */ 373 max_pclk = si->ps.max_dac2_clock_32; 374 break; 375 } 376 /* if some dualhead mode is active, an extra restriction might apply */ 377 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 378 max_pclk = si->ps.max_dac2_clock_32dh; 379 380 /* Make sure the requested pixelclock is within the PLL's operational limits */ 381 /* lower limit is min_video_vco divided by highest postscaler-factor */ 382 if (req_pclk < (si->ps.min_video_vco / 8.0)) 383 { 384 LOG(4, ("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 385 req_pclk, (float)(si->ps.min_video_vco / 8.0))); 386 req_pclk = (si->ps.min_video_vco / 8.0); 387 } 388 /* upper limit is given by pins in combination with current active mode */ 389 if (req_pclk > max_pclk) 390 { 391 LOG(4, ("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 392 req_pclk, (float)max_pclk)); 393 req_pclk = max_pclk; 394 } 395 396 /* iterate through all valid PLL postscaler settings */ 397 for (p=0x01; p < 0x10; p = p<<1) 398 { 399 /* calculate the needed VCO frequency for this postscaler setting */ 400 f_vco = req_pclk * p; 401 402 /* check if this is within range of the VCO specs */ 403 if ((f_vco >= si->ps.min_video_vco) && (f_vco <= si->ps.max_video_vco)) 404 { 405 /* iterate trough all valid reference-frequency postscaler settings */ 406 for (m = 2; m <= m_max; m++) 407 { 408 /* calculate VCO postscaler setting for current setup.. */ 409 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 410 /* ..and check for validity */ 411 if ((n < 8) || (n > 128)) continue; 412 413 /* find error in frequency this setting gives */ 414 error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p)); 415 416 /* note the setting if best yet */ 417 if (error < error_best) 418 { 419 error_best = error; 420 best[0]=m; 421 best[1]=n; 422 best[2]=p; 423 } 424 } 425 } 426 } 427 428 /* setup the scalers programming values for found optimum setting */ 429 m=best[0] - 1; 430 n=best[1] - 1; 431 p=best[2] - 1; 432 433 /* calc the needed PLL loopbackfilter setting belonging to current VCO speed */ 434 f_vco = (si->ps.f_ref / (m + 1)) * (n + 1); 435 LOG(2, ("MAVEN: vid VCO frequency found %fMhz\n", f_vco)); 436 437 switch (si->ps.card_type) 438 { 439 case G100: 440 case G200: 441 for (;;) 442 { 443 if (f_vco >= 180) {p |= (0x03 << 3); break;}; 444 if (f_vco >= 140) {p |= (0x02 << 3); break;}; 445 if (f_vco >= 100) {p |= (0x01 << 3); break;}; 446 break; 447 } 448 break; 449 default: 450 for (;;) 451 { 452 if (f_vco >= 240) {p |= (0x03 << 3); break;}; 453 if (f_vco >= 170) {p |= (0x02 << 3); break;}; 454 if (f_vco >= 110) {p |= (0x01 << 3); break;}; 455 break; 456 } 457 break; 458 } 459 460 /* return the results */ 461 *calc_pclk = f_vco / ((p & 0x07) + 1); 462 *m_result = m; 463 *n_result = n; 464 *p_result = p; 465 466 /* display the found pixelclock values */ 467 LOG(2, ("MAVEN: vid PLL check: req. %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 468 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 469 470 return B_OK; 471 } 472 473 474 static status_t gx50_maven_check_vid_pll(uint8 m, uint8 n, uint8 p) 475 { 476 uint time = 0, count = 0; 477 478 /* reprogram (disable,select,wait for stability,enable) */ 479 CR2W(CTL, (CR2R(CTL) | 0x06)); /* select the VIDPLL */ 480 DXIW(VIDPLLM,(m)); /* set m value */ 481 DXIW(VIDPLLN,(n)); /* set n value */ 482 DXIW(VIDPLLP,(p)); /* set p value */ 483 484 /* give the PLL 1mS at least to get a lock */ 485 time = 0; 486 while((!(DXIR(VIDPLLSTAT) & 0x40)) & (time <= 1000)) 487 { 488 time++; 489 snooze(1); 490 } 491 492 /* no lock aquired, not useable */ 493 if (time > 1000) return B_ERROR; 494 495 /* check if lock holds for at least 90% of the time */ 496 for (time = 0, count = 0; time <= 1000; time++) 497 { 498 if(DXIR(VIDPLLSTAT) & 0x40) count++; 499 snooze(1); 500 } 501 /* we have a winner */ 502 if (count >= 900) return B_OK; 503 504 /* nogo, the PLL does not stabilize */ 505 return B_ERROR; 506 } 507 508 static status_t gx50_maven_check_vid_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q) 509 { 510 uint8 s=0, p_backup = *p; 511 512 /* preset no candidate, non working setting */ 513 *q = 0; 514 /* preset lowest range filter */ 515 *p &= 0x47; 516 517 /* iterate through all possible filtersettings */ 518 CR2W(CTL, (CR2R(CTL) | 0x08)); /* disable the VIDPLL */ 519 520 for (s = 0; s < 8 ;s++) 521 { 522 if (gx50_maven_check_vid_pll(m, n, *p)== B_OK) 523 { 524 /* now check 3 closest lower and higher settings */ 525 if ((gx50_maven_check_vid_pll(m, n - 3, *p)== B_OK) && 526 (gx50_maven_check_vid_pll(m, n - 2, *p)== B_OK) && 527 (gx50_maven_check_vid_pll(m, n - 1, *p)== B_OK) && 528 (gx50_maven_check_vid_pll(m, n + 1, *p)== B_OK) && 529 (gx50_maven_check_vid_pll(m, n + 2, *p)== B_OK) && 530 (gx50_maven_check_vid_pll(m, n + 3, *p)== B_OK)) 531 { 532 LOG(2,("MAVEN: found optimal working VCO filter: #%d\n",s)); 533 /* preset first choice setting found */ 534 *q = 1; 535 /* we are done */ 536 CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */ 537 return B_OK; 538 } 539 else 540 { 541 LOG(2,("MAVEN: found critical but working VCO filter: #%d\n",s)); 542 /* preset backup setting found */ 543 *q = 2; 544 /* remember this setting */ 545 p_backup = *p; 546 /* let's continue to see if a better filter exists */ 547 } 548 } 549 /* new filtersetting to try */ 550 *p += (1 << 3); 551 } 552 553 /* return the (last found) backup result, or the original p value */ 554 *p = p_backup; 555 CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */ 556 /* we found only a non-optimal value */ 557 if (*q == 2) return B_OK; 558 559 /* nothing worked at all */ 560 LOG(2,("MAVEN: no working VCO filter found!\n")); 561 return B_ERROR; 562 } 563 564 565 /* find nearest valid video PLL setting */ 566 status_t g450_g550_maven_vid_pll_find 567 (display_mode target, float* calc_pclk, uint8* m_result, uint8* n_result, 568 uint8* p_result, uint8 test) 569 { 570 int m = 0, n = 0; 571 uint8 p = 0, q = 0; 572 float error, error_best = INFINITY; 573 int best[3] = {0, 0, 0}; 574 float f_vco, max_pclk; 575 float req_pclk = target.timing.pixel_clock/1000.0; 576 577 LOG(4, ("MAVEN: G450/G550 restrictions apply\n")); 578 579 /* determine the max. pixelclock for the current videomode */ 580 switch (target.space) 581 { 582 case B_RGB16_LITTLE: 583 max_pclk = si->ps.max_dac2_clock_16; 584 break; 585 case B_RGB32_LITTLE: 586 max_pclk = si->ps.max_dac2_clock_32; 587 break; 588 default: 589 /* use fail-safe value */ 590 max_pclk = si->ps.max_dac2_clock_32; 591 break; 592 } 593 /* if some dualhead mode is active, an extra restriction might apply */ 594 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 595 max_pclk = si->ps.max_dac2_clock_32dh; 596 597 /* Make sure the requested pixelclock is within the PLL's operational limits */ 598 /* lower limit is min_pixel_vco divided by highest postscaler-factor */ 599 if (req_pclk < (si->ps.min_video_vco / 16.0)) 600 { 601 LOG(4, ("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 602 req_pclk, (float)(si->ps.min_video_vco / 16.0))); 603 req_pclk = (si->ps.min_video_vco / 16.0); 604 } 605 /* upper limit is given by pins in combination with current active mode */ 606 if (req_pclk > max_pclk) 607 { 608 LOG(4, ("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 609 req_pclk, (float)max_pclk)); 610 req_pclk = max_pclk; 611 } 612 613 /* iterate through all valid PLL postscaler settings */ 614 for (p=0x01; p < 0x20; p = p<<1) 615 { 616 /* calculate the needed VCO frequency for this postscaler setting */ 617 f_vco = req_pclk * p; 618 619 /* check if this is within range of the VCO specs */ 620 if ((f_vco >= si->ps.min_video_vco) && (f_vco <= si->ps.max_video_vco)) 621 { 622 /* iterate trough all valid reference-frequency postscaler settings */ 623 for (m = 2; m <= 32; m++) 624 { 625 /* calculate VCO postscaler setting for current setup.. */ 626 n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5); 627 /* ..and check for validity, BUT: 628 * Keep in mind that we need to be able to test n-3 ... n+3! */ 629 if ((n < (8 + 3)) || (n > (128 - 3))) continue; 630 631 /* find error in frequency this setting gives */ 632 error = fabs(req_pclk - ((((si->ps.f_ref * 2)/ m) * n) / p)); 633 634 /* note the setting if best yet */ 635 if (error < error_best) 636 { 637 error_best = error; 638 best[0]=m; 639 best[1]=n; 640 best[2]=p; 641 } 642 } 643 } 644 } 645 646 /* setup the scalers programming values for found optimum setting */ 647 m=best[0] - 1; 648 n=best[1] - 2; 649 switch (best[2]) 650 { 651 case 1: 652 p = 0x40; 653 break; 654 case 2: 655 p = 0x00; 656 break; 657 case 4: 658 p = 0x01; 659 break; 660 case 8: 661 p = 0x02; 662 break; 663 case 16: 664 p = 0x03; 665 break; 666 } 667 668 /* log the closest VCO speed found */ 669 f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2); 670 LOG(2, ("MAVEN: vid VCO frequency found %fMhz\n", f_vco)); 671 672 /* now find the filtersetting that matches best with this frequency by testing. 673 * for now we assume this routine succeeds to get us a stable setting */ 674 if (test) 675 gx50_maven_check_vid_pll_range(m, n, &p, &q); 676 else 677 LOG(2, ("MAVEN: Not testing G450/G550 VCO feedback filters\n")); 678 679 /* return the results */ 680 *calc_pclk = f_vco / best[2]; 681 *m_result = m; 682 *n_result = n; 683 *p_result = p; 684 685 /* display the found pixelclock values */ 686 LOG(2, ("MAVEN: vid PLL check: req. %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 687 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 688 689 return B_OK; 690 } 691