123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "pci.h"
- #include "vga.h"
- #define SCALE(f) ((f)/10) /* could be /10 */
- static void
- init(Vga* vga, Ctlr* ctlr)
- {
- int f, k;
- ulong fmin, fvco, m, n, p, q;
- double z;
- if(ctlr->flag & Finit)
- return;
- if(vga->f[0] == 0)
- vga->f[0] = vga->mode->frequency;
- vga->misc &= ~0x0C;
- if(vga->f[0] == VgaFreq0){
- /* nothing to do */;
- }
- else if(vga->f[0] == VgaFreq1)
- vga->misc |= 0x04;
- else
- vga->misc |= 0x0C;
- /*
- * Look for values of n, d and p that give
- * the least error for
- * Fvco = 8*RefFreq*(65-m)/(65-n)
- * Fpll = Fvco/2**p
- * N and m are 6 bits, p is 2 bits. Constraints:
- * 110MHz <= Fvco <= 250MHz
- * 40 <= n <= 62
- * 1 <= m <= 62
- * 0 <= p <= 3
- * Should try to minimise n, m.
- *
- * There's nothing like brute force and ignorance.
- */
- fmin = vga->f[0];
- vga->m[0] = 0x15;
- vga->n[0] = 0x18;
- vga->p[0] = 3;
- for(m = 62; m > 0; m--){
- for(n = 62; n >= 40; n--){
- fvco = 8*SCALE(RefFreq)*(65-m)/(65-n);
- if(fvco < SCALE(110000000) || fvco > SCALE(250000000))
- continue;
- for(p = 0; p < 4; p++){
- f = SCALE(vga->f[0]) - (fvco>>p);
- if(f < 0)
- f = -f;
- if(f < fmin){
- fmin = f;
- vga->m[0] = m;
- vga->n[0] = n;
- vga->p[0] = p;
- }
- }
- }
- }
- /*
- * Now the loop clock:
- * m is fixed;
- * calculate n;
- * set z to the lower bound (110MHz) and calculate p and q.
- */
- vga->m[1] = 61;
- if(ctlr->flag & Uenhanced)
- k = 64/8;
- else
- k = 8/8;
- n = 65 - 4*k;
- fvco = (8*RefFreq*(65-vga->m[0]))/(65-vga->n[0]);
- vga->f[1] = fvco;
- z = 110.0*(65-n)/(4*(fvco/1000000.0)*k);
- if(z <= 16){
- for(p = 0; p < 4; p++){
- if(1<<(p+1) > z)
- break;
- }
- q = 0;
- }
- else{
- p = 3;
- q = (z - 16)/16 + 1;
- }
- vga->n[1] = n;
- vga->p[1] = p;
- vga->q[1] = q;
- ctlr->flag |= Finit;
- }
- Ctlr tvp3026clock = {
- "tvp3026clock", /* name */
- 0, /* snarf */
- 0, /* options */
- init, /* init */
- 0, /* load */
- 0, /* dump */
- };
|