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 /* find nearest valid video PLL setting */ 333 status_t g100_g400max_maven_vid_pll_find( 334 display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result) 335 { 336 int m = 0, n = 0, p = 0, m_max; 337 float error, error_best = 999999999; 338 int best[3]; 339 float f_vco, max_pclk; 340 float req_pclk = target.timing.pixel_clock/1000.0; 341 342 /* determine the max. reference-frequency postscaler setting for the current card */ 343 //fixme: check G100 and G200 m_max if possible... 344 switch(si->ps.card_type) 345 { 346 case G100: 347 LOG(4,("MAVEN: G100 restrictions apply\n")); 348 m_max = 32; 349 break; 350 case G200: 351 LOG(4,("MAVEN: G200 restrictions apply\n")); 352 m_max = 32; 353 break; 354 default: 355 LOG(4,("MAVEN: G400/G400MAX restrictions apply\n")); 356 m_max = 32; 357 break; 358 } 359 360 /* determine the max. pixelclock for the current videomode */ 361 switch (target.space) 362 { 363 case B_RGB16_LITTLE: 364 max_pclk = si->ps.max_dac2_clock_16; 365 break; 366 case B_RGB32_LITTLE: 367 max_pclk = si->ps.max_dac2_clock_32; 368 break; 369 default: 370 /* use fail-safe value */ 371 max_pclk = si->ps.max_dac2_clock_32; 372 break; 373 } 374 /* if some dualhead mode is active, an extra restriction might apply */ 375 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 376 max_pclk = si->ps.max_dac2_clock_32dh; 377 378 /* Make sure the requested pixelclock is within the PLL's operational limits */ 379 /* lower limit is min_video_vco divided by highest postscaler-factor */ 380 if (req_pclk < (si->ps.min_video_vco / 8.0)) 381 { 382 LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 383 req_pclk, (float)(si->ps.min_video_vco / 8.0))); 384 req_pclk = (si->ps.min_video_vco / 8.0); 385 } 386 /* upper limit is given by pins in combination with current active mode */ 387 if (req_pclk > max_pclk) 388 { 389 LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 390 req_pclk, (float)max_pclk)); 391 req_pclk = max_pclk; 392 } 393 394 /* iterate through all valid PLL postscaler settings */ 395 for (p=0x01; p < 0x10; p = p<<1) 396 { 397 /* calculate the needed VCO frequency for this postscaler setting */ 398 f_vco = req_pclk * p; 399 400 /* check if this is within range of the VCO specs */ 401 if ((f_vco >= si->ps.min_video_vco) && (f_vco <= si->ps.max_video_vco)) 402 { 403 /* iterate trough all valid reference-frequency postscaler settings */ 404 for (m = 2; m <= m_max; m++) 405 { 406 /* calculate VCO postscaler setting for current setup.. */ 407 n = (int)(((f_vco * m) / si->ps.f_ref) + 0.5); 408 /* ..and check for validity */ 409 if ((n < 8) || (n > 128)) continue; 410 411 /* find error in frequency this setting gives */ 412 error = fabs(req_pclk - (((si->ps.f_ref / m) * n) / p)); 413 414 /* note the setting if best yet */ 415 if (error < error_best) 416 { 417 error_best = error; 418 best[0]=m; 419 best[1]=n; 420 best[2]=p; 421 } 422 } 423 } 424 } 425 426 /* setup the scalers programming values for found optimum setting */ 427 m=best[0] - 1; 428 n=best[1] - 1; 429 p=best[2] - 1; 430 431 /* calc the needed PLL loopbackfilter setting belonging to current VCO speed */ 432 f_vco = (si->ps.f_ref / (m + 1)) * (n + 1); 433 LOG(2,("MAVEN: vid VCO frequency found %fMhz\n", f_vco)); 434 435 switch(si->ps.card_type) 436 { 437 case G100: 438 case G200: 439 for(;;) 440 { 441 if (f_vco >= 180) {p |= (0x03 << 3); break;}; 442 if (f_vco >= 140) {p |= (0x02 << 3); break;}; 443 if (f_vco >= 100) {p |= (0x01 << 3); break;}; 444 break; 445 } 446 break; 447 default: 448 for(;;) 449 { 450 if (f_vco >= 240) {p |= (0x03 << 3); break;}; 451 if (f_vco >= 170) {p |= (0x02 << 3); break;}; 452 if (f_vco >= 110) {p |= (0x01 << 3); break;}; 453 break; 454 } 455 break; 456 } 457 458 /* return the results */ 459 *calc_pclk = f_vco / ((p & 0x07) + 1); 460 *m_result = m; 461 *n_result = n; 462 *p_result = p; 463 464 /* display the found pixelclock values */ 465 LOG(2,("MAVEN: vid PLL check: req. %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 466 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 467 468 return B_OK; 469 } 470 471 static status_t gx50_maven_check_vid_pll(uint8 m, uint8 n, uint8 p) 472 { 473 uint time = 0, count = 0; 474 475 /* reprogram (disable,select,wait for stability,enable) */ 476 CR2W(CTL, (CR2R(CTL) | 0x06)); /* select the VIDPLL */ 477 DXIW(VIDPLLM,(m)); /* set m value */ 478 DXIW(VIDPLLN,(n)); /* set n value */ 479 DXIW(VIDPLLP,(p)); /* set p value */ 480 481 /* give the PLL 1mS at least to get a lock */ 482 time = 0; 483 while((!(DXIR(VIDPLLSTAT) & 0x40)) & (time <= 1000)) 484 { 485 time++; 486 snooze(1); 487 } 488 489 /* no lock aquired, not useable */ 490 if (time > 1000) return B_ERROR; 491 492 /* check if lock holds for at least 90% of the time */ 493 for (time = 0, count = 0; time <= 1000; time++) 494 { 495 if(DXIR(VIDPLLSTAT) & 0x40) count++; 496 snooze(1); 497 } 498 /* we have a winner */ 499 if (count >= 900) return B_OK; 500 501 /* nogo, the PLL does not stabilize */ 502 return B_ERROR; 503 } 504 505 static status_t gx50_maven_check_vid_pll_range(uint8 m, uint8 n, uint8 *p, uint8 *q) 506 { 507 uint8 s=0, p_backup = *p; 508 509 /* preset no candidate, non working setting */ 510 *q = 0; 511 /* preset lowest range filter */ 512 *p &= 0x47; 513 514 /* iterate through all possible filtersettings */ 515 CR2W(CTL, (CR2R(CTL) | 0x08)); /* disable the VIDPLL */ 516 517 for (s = 0; s < 8 ;s++) 518 { 519 if (gx50_maven_check_vid_pll(m, n, *p)== B_OK) 520 { 521 /* now check 3 closest lower and higher settings */ 522 if ((gx50_maven_check_vid_pll(m, n - 3, *p)== B_OK) && 523 (gx50_maven_check_vid_pll(m, n - 2, *p)== B_OK) && 524 (gx50_maven_check_vid_pll(m, n - 1, *p)== B_OK) && 525 (gx50_maven_check_vid_pll(m, n + 1, *p)== B_OK) && 526 (gx50_maven_check_vid_pll(m, n + 2, *p)== B_OK) && 527 (gx50_maven_check_vid_pll(m, n + 3, *p)== B_OK)) 528 { 529 LOG(2,("MAVEN: found optimal working VCO filter: #%d\n",s)); 530 /* preset first choice setting found */ 531 *q = 1; 532 /* we are done */ 533 CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */ 534 return B_OK; 535 } 536 else 537 { 538 LOG(2,("MAVEN: found critical but working VCO filter: #%d\n",s)); 539 /* preset backup setting found */ 540 *q = 2; 541 /* remember this setting */ 542 p_backup = *p; 543 /* let's continue to see if a better filter exists */ 544 } 545 } 546 /* new filtersetting to try */ 547 *p += (1 << 3); 548 } 549 550 /* return the (last found) backup result, or the original p value */ 551 *p = p_backup; 552 CR2W(CTL, (CR2R(CTL) & ~0x08)); /* enable the VIDPLL */ 553 /* we found only a non-optimal value */ 554 if (*q == 2) return B_OK; 555 556 /* nothing worked at all */ 557 LOG(2,("MAVEN: no working VCO filter found!\n")); 558 return B_ERROR; 559 } 560 561 /* find nearest valid video PLL setting */ 562 status_t g450_g550_maven_vid_pll_find 563 (display_mode target,float * calc_pclk,uint8 * m_result,uint8 * n_result,uint8 * p_result, uint8 test) 564 { 565 int m = 0, n = 0; 566 uint8 p = 0, q = 0; 567 float error, error_best = 999999999; 568 int best[3]; 569 float f_vco, max_pclk; 570 float req_pclk = target.timing.pixel_clock/1000.0; 571 572 LOG(4,("MAVEN: G450/G550 restrictions apply\n")); 573 574 /* determine the max. pixelclock for the current videomode */ 575 switch (target.space) 576 { 577 case B_RGB16_LITTLE: 578 max_pclk = si->ps.max_dac2_clock_16; 579 break; 580 case B_RGB32_LITTLE: 581 max_pclk = si->ps.max_dac2_clock_32; 582 break; 583 default: 584 /* use fail-safe value */ 585 max_pclk = si->ps.max_dac2_clock_32; 586 break; 587 } 588 /* if some dualhead mode is active, an extra restriction might apply */ 589 if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE)) 590 max_pclk = si->ps.max_dac2_clock_32dh; 591 592 /* Make sure the requested pixelclock is within the PLL's operational limits */ 593 /* lower limit is min_pixel_vco divided by highest postscaler-factor */ 594 if (req_pclk < (si->ps.min_video_vco / 16.0)) 595 { 596 LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 597 req_pclk, (float)(si->ps.min_video_vco / 16.0))); 598 req_pclk = (si->ps.min_video_vco / 16.0); 599 } 600 /* upper limit is given by pins in combination with current active mode */ 601 if (req_pclk > max_pclk) 602 { 603 LOG(4,("MAVEN: clamping vidclock: requested %fMHz, set to %fMHz\n", 604 req_pclk, (float)max_pclk)); 605 req_pclk = max_pclk; 606 } 607 608 /* iterate through all valid PLL postscaler settings */ 609 for (p=0x01; p < 0x20; p = p<<1) 610 { 611 /* calculate the needed VCO frequency for this postscaler setting */ 612 f_vco = req_pclk * p; 613 614 /* check if this is within range of the VCO specs */ 615 if ((f_vco >= si->ps.min_video_vco) && (f_vco <= si->ps.max_video_vco)) 616 { 617 /* iterate trough all valid reference-frequency postscaler settings */ 618 for (m = 2; m <= 32; m++) 619 { 620 /* calculate VCO postscaler setting for current setup.. */ 621 n = (int)(((f_vco * m) / (si->ps.f_ref * 2)) + 0.5); 622 /* ..and check for validity, BUT: 623 * Keep in mind that we need to be able to test n-3 ... n+3! */ 624 if ((n < (8 + 3)) || (n > (128 - 3))) continue; 625 626 /* find error in frequency this setting gives */ 627 error = fabs(req_pclk - ((((si->ps.f_ref * 2)/ m) * n) / p)); 628 629 /* note the setting if best yet */ 630 if (error < error_best) 631 { 632 error_best = error; 633 best[0]=m; 634 best[1]=n; 635 best[2]=p; 636 } 637 } 638 } 639 } 640 641 /* setup the scalers programming values for found optimum setting */ 642 m=best[0] - 1; 643 n=best[1] - 2; 644 switch(best[2]) 645 { 646 case 1: 647 p = 0x40; 648 break; 649 case 2: 650 p = 0x00; 651 break; 652 case 4: 653 p = 0x01; 654 break; 655 case 8: 656 p = 0x02; 657 break; 658 case 16: 659 p = 0x03; 660 break; 661 } 662 663 /* log the closest VCO speed found */ 664 f_vco = ((si->ps.f_ref * 2) / (m + 1)) * (n + 2); 665 LOG(2,("MAVEN: vid VCO frequency found %fMhz\n", f_vco)); 666 667 /* now find the filtersetting that matches best with this frequency by testing. 668 * for now we assume this routine succeeds to get us a stable setting */ 669 if (test) 670 gx50_maven_check_vid_pll_range(m, n, &p, &q); 671 else 672 LOG(2,("MAVEN: Not testing G450/G550 VCO feedback filters\n")); 673 674 /* return the results */ 675 *calc_pclk = f_vco / best[2]; 676 *m_result = m; 677 *n_result = n; 678 *p_result = p; 679 680 /* display the found pixelclock values */ 681 LOG(2,("MAVEN: vid PLL check: req. %fMHz got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n", 682 req_pclk, *calc_pclk, *m_result, *n_result, *p_result)); 683 684 return B_OK; 685 } 686