diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/vga/tvp3026clock.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/vga/tvp3026clock.c')
-rwxr-xr-x | sys/src/cmd/aux/vga/tvp3026clock.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/vga/tvp3026clock.c b/sys/src/cmd/aux/vga/tvp3026clock.c new file mode 100755 index 000000000..787e6ae48 --- /dev/null +++ b/sys/src/cmd/aux/vga/tvp3026clock.c @@ -0,0 +1,108 @@ +#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 */ +}; |