vmodes.c revision 0b661123
1/* 2 * file vmodes.c 3 * 4 * Routines that handle mode setting. 5 */ 6 7#ifdef HAVE_CONFIG_H 8#include "config.h" 9#endif 10 11/* 12 * includes 13 */ 14 15#include "rendition.h" 16#include "vmodes.h" 17#include "vos.h" 18#include "vramdac.h" 19#include "v1krisc.h" 20#include "v1kregs.h" 21#include "v2kregs.h" 22 23 24#undef DEBUG 25 26 27/* 28 * defines 29 */ 30 31#define combineNMP(N, M, P) \ 32 (((vu32)(M-2)<<10) | ((vu32)P<<8) | (vu32)(N-2)) 33 34#define v2kcombineNMP(N, M, P) (((vu32)N<<13) | ((vu32)P<<9) | (vu32)M) 35 36/* defines for doubled clock */ 37#define CLK_DOUBLE 1 38#define NO_CLK_DOUBLE 0 39 40/* video FIFO is set to 64 or 128 entries based on req.d bandwidth in bytes/s */ 41#define FIFOSIZE_THRESH 100000000 /* set thresh to 100MB/s */ 42 43/* compute desired video FIFO size given total bandwidth in bytes/s. */ 44#define FIFOSIZE(vclk, Bpp) (((vclk * Bpp) > FIFOSIZE_THRESH) ? 128 : 64) 45 46/* Bt485A RAMDAC control bits */ 47#define PALETTEDISABLE 0x10 48 49/* Hold memory refresh cycles until video blank */ 50#define HOLD_MEMREFRESHCYCLE 0x2000 51 52/* memCtl bits [16..23] */ 53#define DEFAULT_WREFRESH 0x330000 54 55/* Disable memory refresh cycles */ 56#define DISABLE_MEMREFRESHCYCLE 0x8000 57 58#define CTL(ldbl, hsynchi, vsynchi) \ 59 (((ldbl) ? CRTCCTL_LINEDOUBLE : 0) \ 60 |((hsynchi) ? CRTCCTL_HSYNCHI : 0) \ 61 |((vsynchi) ? CRTCCTL_VSYNCHI : 0) \ 62 |(CRTCCTL_VSYNCENABLE | CRTCCTL_HSYNCENABLE)) 63 64#define HORZ(fp, sy, bp, ac) \ 65 (((((vu32)(((fp)>>3)-1))&7)<<21)|((((vu32)(((sy)>>3)-1))&0x1F)<<16)|((((vu32)(((bp)>>3)-1))&0x3f)<<9)|((((vu32)(((ac)>>3)-1))&0xff))) 66 67#define VERT(fp, sy, bp, ac) \ 68 (((((vu32)(fp-1))&0x3f)<<20)|((((vu32)(sy-1))&0x7)<<17)|((((vu32)(bp-1))&0x3f)<<11)|((((vu32)(ac-1))&0x7ff))) 69 70#define HORZAC(crtchorz) \ 71 (((((vu32)crtchorz)&CRTCHORZ_ACTIVE_MASK)+1)<<3) 72 73#define HORZBP(crtchorz) \ 74 ((((((vu32)crtchorz)&CRTCHORZ_BACKPORCH_MASK)>>9)+1)<<3) 75 76#define HORZSY(crtchorz) \ 77 ((((((vu32)crtchorz)&CRTCHORZ_SYNC_MASK)>>16)+1)<<3) 78 79#define HORZFP(crtchorz) \ 80 ((((((vu32)crtchorz)&CRTCHORZ_FRONTPORCH_MASK)>>21)+1)<<3) 81 82#define VERTAC(crtcvert) \ 83 ((((vu32)crtcvert)&CRTCVERT_ACTIVE_MASK)+1) 84 85#define VERTBP(crtcvert) \ 86 (((((vu32)crtcvert)&CRTCVERT_BACKPORCH_MASK)>>11)+1) 87 88#define VERTSY(crtcvert) \ 89 (((((vu32)crtcvert)&CRTCVERT_SYNC_MASK)>>17)+1) 90 91#define VERTFP(crtcvert) \ 92 (((((vu32)crtcvert)&CRTCVERT_FRONTPORCH_MASK)>>20)+1) 93 94#define PCLK(N, M, P) (N),(M),(P) 95 96#define TIMING_MASK (CRTCCTL_VIDEOFIFOSIZE128|CRTCCTL_LINEDOUBLE|\ 97 CRTCCTL_VSYNCHI|CRTCCTL_HSYNCHI|CRTCCTL_VSYNCENABLE|\ 98 CRTCCTL_HSYNCENABLE) 99 100/* addr&7 == 5, 6, 7 are bad */ 101#define BADADDR(x) (((x)&(((x)<<1)|((x)<<2)))&0x4) 102 103#define V1_MIN_VCO_FREQ 25 104#define V1_MAX_VCO_FREQ 135 105#define V1_REF_FREQ 14.318 106#define V1_MIN_PCF_FREQ 0.2 107#define V1_MAX_PCF_FREQ 5 108 109#define V2_MIN_VCO_FREQ 125 110#define V2_MAX_VCO_FREQ 250 111#define V2_REF_FREQ 14.31818 /* Eh, is this right? */ 112#define V2_MIN_PCF_FREQ 1 113#define V2_MAX_PCF_FREQ 3 114 115 116 117/* 118 * global data 119 */ 120 121static struct width_to_stride_t { 122 vu32 width8bpp; 123 vu8 stride0; 124 vu8 stride1; 125 vu16 chip; 126} width_to_stride_table[]={ 127/* { 0, 0, 0, V1000_DEVICE }, */ 128 { 4, 4, 0, V1000_DEVICE }, 129 { 16, 0, 1, V1000_DEVICE }, 130 { 20, 4, 1, V1000_DEVICE }, 131 { 32, 0, 2, V1000_DEVICE }, 132 { 36, 4, 2, V1000_DEVICE }, 133 { 64, 0, 3, V1000_DEVICE }, 134 { 68, 4, 3, V1000_DEVICE }, 135 { 128, 0, 4, V1000_DEVICE }, 136 { 132, 4, 4, V1000_DEVICE }, 137 { 256, 1, 0, V1000_DEVICE }, 138 { 272, 1, 1, V1000_DEVICE }, 139 { 288, 1, 2, V1000_DEVICE }, 140 { 320, 1, 3, V1000_DEVICE }, 141 { 384, 1, 4, V1000_DEVICE }, 142 { 512, 2, 0, V1000_DEVICE }, 143 { 528, 2, 1, V1000_DEVICE }, 144 { 544, 2, 2, V1000_DEVICE }, 145 { 576, 2, 3, V1000_DEVICE }, 146 { 592, 6, 1, V2000_DEVICE }, 147 { 608, 6, 2, V2000_DEVICE }, 148 { 640, 2, 4, V1000_DEVICE }, 149 { 704, 6, 4, V2000_DEVICE }, 150 { 768, 5, 0, V2000_DEVICE }, 151 { 784, 5, 1, V2000_DEVICE }, 152 { 800, 5, 2, V2000_DEVICE }, 153 { 832, 5, 3, V2000_DEVICE }, 154 { 896, 5, 4, V2000_DEVICE }, 155 { 1024, 3, 0, V1000_DEVICE }, 156 { 1028, 4, 5, V1000_DEVICE }, 157 { 1040, 3, 1, V1000_DEVICE }, 158 { 1056, 3, 2, V1000_DEVICE }, 159 { 1088, 3, 3, V1000_DEVICE }, 160 { 1152, 3, 4, V1000_DEVICE }, 161 { 1168, 7, 1, V2000_DEVICE }, 162 { 1184, 7, 2, V2000_DEVICE }, 163 { 1216, 7, 3, V2000_DEVICE }, 164 { 1280, 1, 5, V1000_DEVICE }, 165 { 1536, 2, 5, V1000_DEVICE }, 166 { 1600, 6, 5, V2000_DEVICE }, 167 { 1792, 5, 5, V2000_DEVICE }, 168 { 2048, 0, 6, V1000_DEVICE }, 169 { 2052, 4, 6, V1000_DEVICE }, 170 { 2176, 7, 5, V2000_DEVICE }, 171 { 2304, 1, 6, V1000_DEVICE }, 172 { 2560, 2, 6, V1000_DEVICE }, 173 { 2624, 6, 6, V2000_DEVICE }, 174 { 2816, 5, 6, V2000_DEVICE }, 175 { 3072, 3, 6, V1000_DEVICE }, 176 { 3200, 7, 6, V2000_DEVICE }, 177 { 4096, 0, 7, V1000_DEVICE }, 178 { 4100, 4, 7, V1000_DEVICE }, 179 { 4352, 1, 7, V1000_DEVICE }, 180 { 4608, 2, 7, V1000_DEVICE }, 181 { 4672, 6, 7, V2000_DEVICE }, 182 { 4864, 5, 7, V2000_DEVICE }, 183 { 5120, 3, 7, V1000_DEVICE }, 184 { 5248, 7, 7, V2000_DEVICE }, 185 { 0, 0, 0, 0 } 186}; 187 188struct V1000ClocksStr { 189 int h_size; 190 int pll_val; 191} V1000Clocks [] = { 192 { 72, 0x40000 }, /* For Textmode */ 193 { 640, 0x2408 }, /* 31500 MHz */ 194 { 800, 0x1583D }, /* 40000 MHz */ 195 { 1024, 0x14823 }, /* 65000 MHz */ 196 { 1280, 0x14414 }, /* 108000 MHz */ 197 { 0, 0 } 198}; 199 200/* 201 * local function prototypes 202 */ 203 204static void set_PLL(IOADDRESS iob, vu32 value); 205static double V1000CalcClock(double target, int *M, int *N, int *P); 206static double V2200CalcClock(double target, int *m, int *n, int *p); 207 208 209 210/* 211 * functions 212 */ 213 214int 215verite_setmode(ScrnInfoPtr pScreenInfo, struct verite_modeinfo_t *mode) 216{ 217 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 218 219 int tmp; 220 int doubleclock=0; 221 int M, N, P; 222 int iob=pRendition->board.io_base; 223 224#ifdef DEBUG 225 ErrorF ("Rendition: Debug verite_setmode called\n"); 226#endif 227 228 /* switching to native mode */ 229 verite_out8(iob+MODEREG, NATIVE_MODE|VESA_MODE); 230 231 /* flipping some bytes */ 232 /* Must be something better to do than this -- FIX */ 233 switch (mode->bitsperpixel) { 234 case 32: 235 verite_out8(iob+MEMENDIAN, MEMENDIAN_NO); 236 break; 237 case 16: 238 verite_out8(iob+MEMENDIAN, MEMENDIAN_HW); 239 break; 240 case 8: 241 verite_out8(iob+MEMENDIAN, MEMENDIAN_END); 242 break; 243 } 244 245 if (pRendition->board.chip != V1000_DEVICE) { 246 if(!pRendition->board.overclock_mem){ 247 verite_out32(iob+SCLKPLL, 0xa484d); /* mclk=110 sclk=50 */ 248 /* M/N/P/P = 77/5/2/4 */ 249 } 250 else{ 251 xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG, 252 (" *** OVERCLOCKING MEM/CLK mclk=125 sclk=60 ***\n")); 253 /* increase Mem/Sys clock on request */ 254 verite_out32(iob+SCLKPLL, 0xa4854); /* mclk=125 sclk=60 */ 255 /* M/N/P/P = 84/5/2/4 */ 256 } 257 usleep(500); 258 } 259 260 /* this has something to do with memory */ 261 tmp=verite_in32(iob+DRAMCTL)&0xdfff; /* reset bit 13 */ 262 verite_out32(iob+DRAMCTL, tmp|0x330000); 263 264 /* program pixel clock */ 265 if (pRendition->board.chip == V1000_DEVICE) { 266 if (110.0 < V1000CalcClock(mode->clock/1000.0, &M, &N, &P)) { 267 P++; 268 doubleclock=1; 269 } 270 set_PLL(iob, combineNMP(N, M, P)); 271 } 272 else { 273 tmp = (~0x1800) & verite_in32(iob+DRAMCTL); 274 verite_out32(iob+DRAMCTL, tmp); 275 V2200CalcClock(mode->clock/1000.0, &M, &N, &P); 276 verite_out32(iob+PCLKPLL, v2kcombineNMP(N, M, P)); 277 } 278 usleep(500); 279 280 /* init the ramdac */ 281 verite_initdac(pScreenInfo, mode->bitsperpixel, doubleclock); 282 283 verite_out32(iob+CRTCHORZ, HORZ(mode->hsyncstart - mode->hdisplay, 284 mode->hsyncend - mode->hsyncstart, 285 mode->htotal - mode->hsyncend, 286 mode->hdisplay)); 287 verite_out32(iob+CRTCVERT, VERT(mode->vsyncstart-mode->vdisplay, 288 mode->vsyncend-mode->vsyncstart, 289 mode->vtotal-mode->vsyncend, 290 mode->vdisplay)); 291 292 /* fill in the mode parameters */ 293 memcpy(&(pRendition->board.mode), mode, sizeof(struct verite_modeinfo_t)); 294 pRendition->board.mode.fifosize=128; 295 pRendition->board.mode.pll_m=M; 296 pRendition->board.mode.pll_n=N; 297 pRendition->board.mode.pll_p=P; 298 pRendition->board.mode.doubleclock=doubleclock; 299 if (0 == pRendition->board.mode.virtualwidth) 300 pRendition->board.mode.virtualwidth=pRendition->board.mode.screenwidth; 301 302 pRendition->board.init=1; 303 (*pScreenInfo->AdjustFrame)(pScreenInfo->scrnIndex, 304 pScreenInfo->frameX0, pScreenInfo->frameY0, 0); 305 306 /* Need to fix up syncs */ 307 308 /* enable the display */ 309 verite_out32(iob+CRTCCTL, CTL(0, mode->hsynchi, mode->vsynchi) 310 |mode->pixelformat 311 |CRTCCTL_VIDEOFIFOSIZE128 312 |CRTCCTL_HSYNCENABLE 313 |CRTCCTL_VSYNCENABLE 314 |CRTCCTL_VIDEOENABLE); 315 316#ifdef DEBUG 317 ErrorF ("Interlace mode -> %d\n", mode->flags); 318 xf86sleep(10);ErrorF ("...Exit SetMode...\n"); 319#endif 320 321 return 0; 322} 323 324static double 325verite_findtextclock(int width) 326{ 327 int i = 0, val; 328 while ((val = V1000Clocks[i].h_size) > 0) { 329 if (val > width) 330 break; 331 else 332 i++; 333 } 334 if (i > 0) i--; 335 return V1000Clocks[i].pll_val; 336} 337 338void 339verite_save(ScrnInfoPtr pScreenInfo) 340{ 341 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 342 int iob=pRendition->board.io_base; 343 RenditionRegPtr reg = &pRendition->saveRegs; 344 345 reg->memendian = verite_in8(iob+MEMENDIAN); 346 reg->mode = verite_in8(iob+MODEREG); 347 reg->sclkpll = verite_in32(iob+SCLKPLL); 348 reg->dramctl = verite_in32(iob+DRAMCTL); 349 reg->crtch = verite_in32(iob+CRTCHORZ); 350 reg->crtcv = verite_in32(iob+CRTCVERT); 351 /* clock */ 352 if (V1000_DEVICE ==pRendition->board.chip) { 353 int width; 354 /* 355 * I have no idea how to read back the clock from 356 * V1000. Therefore we pick a VESA Mode clock from 357 * a list for the width found. 358 */ 359 width = ((reg->crtch & 0xff) + 1) << 3; 360 reg->pclkpll = verite_findtextclock(width); 361 reg->plldev= verite_in8(iob+PLLDEV); 362 } else { 363 reg->pclkpll = verite_in32(iob+PCLKPLL); 364 } 365 /* initdac */ 366 verite_out8(iob+MODEREG,NATIVE_MODE); 367 verite_savedac(pScreenInfo); 368 verite_out8(iob+MODEREG,reg->mode); 369 370 reg->vbasea = verite_in32(iob+FRAMEBASEA); 371 reg->crtcoff = verite_in32(iob+CRTCOFFSET); 372 reg->crtcctl = verite_in32(iob+CRTCCTL); 373} 374 375void 376verite_restore(ScrnInfoPtr pScreenInfo, RenditionRegPtr reg) 377{ 378 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 379 int iob=pRendition->board.io_base; 380 381 verite_restoredac (pScreenInfo, reg); 382 /* 383 * If this is a Verite 1000, restore the MODEREG 384 * register now. The MODEREG gets restored later 385 * for the Verite 2x00 because restoring it here 386 * has been confirmed to cause intermittent 387 * system locks. 388 */ 389 if (pRendition->board.chip == V1000_DEVICE) { 390 verite_out32(iob+MODEREG,reg->mode); 391 } 392 verite_out8(iob+MEMENDIAN,reg->memendian); 393 verite_out32(iob+DRAMCTL,reg->dramctl); 394 verite_out32(iob+SCLKPLL,reg->sclkpll); 395 if (pRendition->board.chip == V1000_DEVICE) { 396 /* fixme */ 397 set_PLL(iob, reg->pclkpll); 398 usleep(10000); 399 } else { 400 verite_out32(iob+PCLKPLL,reg->pclkpll); 401 /* 402 * Need to wait 200uS for PLL to stabilize -- 403 * let's play it safe with 500 404 */ 405 usleep(10000); 406 /* wait until VBLANK */ 407 while ((verite_in32(iob+CRTCSTATUS)&CRTCSTATUS_VERT_MASK) != 408 CRTCSTATUS_VERT_ACTIVE); 409 while ((verite_in32(iob+CRTCSTATUS)&CRTCSTATUS_VERT_MASK) == 410 CRTCSTATUS_VERT_ACTIVE); 411 } 412 413 /* 414 * If this is a Verite 2x00, restore the MODEREG 415 * register now. The MODEREG register is restored 416 * earlier for the Verite 1000, but is restored 417 * here for the Verite 2x00 to prevent system 418 * locks. 419 */ 420 if (pRendition->board.chip != V1000_DEVICE) { 421 verite_out32(iob+MODEREG,reg->mode); 422 } 423 424 verite_out32(iob+CRTCHORZ,reg->crtch); 425 verite_out32(iob+CRTCVERT,reg->crtcv); 426 verite_out32(iob+FRAMEBASEA, reg->vbasea); 427 verite_out32(iob+CRTCOFFSET,reg->crtcoff); 428 verite_out32(iob+CRTCCTL,reg->crtcctl); 429} 430 431void 432verite_setframebase(ScrnInfoPtr pScreenInfo, vu32 framebase) 433{ 434 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 435 436 vu32 offset; 437 438 int iob=pRendition->board.io_base; 439 int swidth=pRendition->board.mode.screenwidth; 440 int vwidth= pRendition->board.mode.virtualwidth; 441 int bytespp=pRendition->board.mode.bitsperpixel>>3; 442 int fifo_size=pRendition->board.mode.fifosize; 443 444#ifdef DEBUG 445 ErrorF( "Rendition: Debug verite_setframebase w=%d v=%d b=%d f=%d\n", 446 swidth, vwidth, bytespp, fifo_size); 447#endif 448 449 /* CRTCOFFSET */ 450 offset=vwidth*bytespp /* virtual width in bytes */ 451 -swidth*bytespp /* screen width in bytes */ 452 +((swidth*bytespp)%fifo_size) /* width in bytes modulo fifo size */ 453 ; 454 455 if (!( framebase&7 /* framebase multiple of 8? */ 456 || (swidth*bytespp)%128)) /* screenwidth multiple of fifo size */ 457 offset+=fifo_size; /* increment offset by fifosize */ 458 459 /* wait for vertical retrace */ 460#ifndef DEBUG 461 if (!pRendition->board.init) { 462 while ((verite_in32(iob+CRTCSTATUS) & CRTCSTATUS_VERT_MASK) != 463 CRTCSTATUS_VERT_ACTIVE) ; 464 while ((verite_in32(iob+CRTCSTATUS) & CRTCSTATUS_VERT_MASK) == 465 CRTCSTATUS_VERT_ACTIVE) ; 466 } 467 else 468 pRendition->board.init=0; 469#endif 470 471 /* framebase */ 472 verite_out32(iob+FRAMEBASEA, framebase); 473 474 /* crtc offset */ 475 verite_out32(iob+CRTCOFFSET, offset&0xffff); 476} 477 478int 479verite_getstride(ScrnInfoPtr pScreenInfo, int *width, 480 vu16 *stride0, vu16 *stride1) 481{ 482 renditionPtr pRendition = RENDITIONPTR(pScreenInfo); 483 int bytesperline; 484 int c = 0; 485 486 bytesperline 487 = pRendition->board.mode.virtualwidth 488 * (pRendition->board.mode.bitsperpixel >> 3); 489#ifdef DEBUG 490 ErrorF("RENDITION: %d bytes per line\n", bytesperline); 491#endif 492 493 /* for now, I implemented a linear search only, should be fixed <ml> */ 494 while (0 != width_to_stride_table[c].width8bpp) { 495 if (width_to_stride_table[c].width8bpp == bytesperline 496 && ((width_to_stride_table[c].chip == pRendition->board.chip) 497 || (V2000_DEVICE == pRendition->board.chip))) { 498 *stride0 = width_to_stride_table[c].stride0; 499 *stride1 = width_to_stride_table[c].stride1; 500 return 1; 501 } 502 c++; 503 } 504 return 0; 505} 506 507/* 508 * local functions 509 */ 510 511/* 512 * void set_PLL(IOADDRESS iob, vu32 value) 513 * 514 * Set PLL clock to desired frequency for the V1000. 515 */ 516 517void 518set_PLL(IOADDRESS iob, vu32 value) 519{ 520 vu32 ulD; 521 int b; 522 523 /* shift out the 20 serial bits */ 524 for (b=19; b>=0; b--) { 525 ulD=(value>>b)&1; 526 verite_out8(iob+PLLDEV, (vu8)ulD); 527 } 528 529 /* read PLL device so the latch is filled with the previously 530 * written value */ 531 (void)verite_in8(iob+PLLDEV); 532} 533 534 535 536/* Vxx00CalcClock -- finds PLL parameters to match target 537 * frequency (in megahertz) 538 * 539 * Brute force, but takes less than a tenth 540 * of a second and the function is only called 541 * O(1) times during program execution. 542 */ 543static double 544V1000CalcClock(double target, int *M, int *N, int *P) 545{ 546 double mindiff = 1e10; 547 double vco, pcf, diff, freq; 548 int mm, nn, pp; 549 550 for (pp=0; pp<4; pp++) 551 for (nn=1; nn<=129; nn++) 552 for (mm=1; mm<=129; mm++) { 553 vco=V1_REF_FREQ*2.0*mm/nn; 554 if ((vco<V1_MIN_VCO_FREQ) || (vco>V1_MAX_VCO_FREQ)) 555 continue; 556 pcf = V1_REF_FREQ/nn; 557 if ((pcf<V1_MIN_PCF_FREQ) || (pcf>V1_MAX_PCF_FREQ)) 558 continue; 559 freq=vco/(1<<pp); 560 diff=fabs(target-freq); 561 if (diff < mindiff) { 562 *M=mm; 563 *N=nn; 564 *P=pp; 565 mindiff=diff; 566 } 567 } 568 569 vco=V1_REF_FREQ*2*(*M)/(*N); 570 pcf=V1_REF_FREQ/(*N); 571 freq=vco/(1<<(*P)); 572 573#ifdef DEBUG 574 ErrorF( 575 "RENDITION: target=%f freq=%f vco=%f pcf=%f n=%d m=%d p=%d\n", 576 target, freq, vco, pcf, *N, *M, *P); 577#endif 578 579 return freq; 580} 581 582 583 584static double 585V2200CalcClock(double target, int *m, int *n, int *p) 586{ 587 double mindiff = 1e10; 588 double vco, pcf, diff, freq; 589 int mm, nn, pp; 590 591 for (pp=1; pp<=0x0f; pp++) 592 for (nn=1; nn<=0x3f; nn++) 593 for (mm=1; mm<=0xff; mm++) { 594 vco = V2_REF_FREQ*mm/nn; 595 if ((vco < V2_MIN_VCO_FREQ) || (vco > V2_MAX_VCO_FREQ)) 596 continue; 597 pcf = V2_REF_FREQ*mm/nn; 598 if ((vco < V2_MIN_VCO_FREQ) || (vco > V2_MAX_VCO_FREQ)) 599 continue; 600 pcf = V2_REF_FREQ/nn; 601 if ((pcf < V2_MIN_PCF_FREQ) || (pcf > V2_MAX_PCF_FREQ)) 602 continue; 603 freq = vco/pp; 604 diff = fabs(target-freq); 605 if (diff < mindiff) { 606 *m = mm; *n = nn; *p = pp; 607 mindiff = diff; 608 } 609 } 610 611 vco = V2_REF_FREQ * *m / *n; 612 pcf = V2_REF_FREQ / *n; 613 freq = vco / *p; 614 615#ifdef DEBUG 616 ErrorF( 617 "RENDITION: target=%f freq=%f vco=%f pcf=%f n=%d m=%d p=%d\n", 618 target, freq, vco, pcf, *n, *m, *p); 619#endif 620 621 return freq; 622} 623 624 625/* 626 * end of file vmodes.c 627 */ 628 629