1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 #define SCALE(f) ((f)/1) /* could be /10 */
9
10 static void
init(Vga * vga,Ctlr * ctlr)11 init(Vga* vga, Ctlr* ctlr)
12 {
13 int f;
14 ulong d, dmax, fmin, fvco, n, nmax, p;
15
16 if(ctlr->flag & Finit)
17 return;
18
19 if(vga->f[0] == 0)
20 vga->f[0] = vga->mode->frequency;
21
22 /*
23 * Look for values of n, d and p that give
24 * the least error for
25 * Fvco = RefFreq*((n+2)*8)/(d+2)
26 * Fpll = Fvco/2**p
27 * N and d are 7-bits, p is 2-bits. Constraints:
28 * RefFreq/(n+2) > 1MHz
29 * 110MHz <= Fvco <= 220MHz
30 * n, d >= 1
31 * Should try to minimise n, d.
32 *
33 * There's nothing like brute force and ignorance.
34 */
35 fmin = vga->f[0];
36 vga->d[0] = 6;
37 vga->n[0] = 5;
38 vga->p[0] = 2;
39 dmax = (RefFreq/1000000)-2;
40 for(d = 1; d < dmax; d++){
41 /*
42 * Calculate an upper bound on n
43 * to satisfy the condition
44 * Fvco <= 220MHz
45 * This will hopefully prevent arithmetic
46 * overflow.
47 */
48 nmax = ((220000000+RefFreq)*(d+2))/(RefFreq*8) - 2;
49 for(n = 1; n < nmax; n++){
50 fvco = SCALE(RefFreq)*((n+2)*8)/(d+2);
51 if(fvco < SCALE(110000000) || fvco > SCALE(220000000))
52 continue;
53 for(p = 1; p < 4; p++){
54 f = SCALE(vga->f[0]) - (fvco>>p);
55 if(f < 0)
56 f = -f;
57 if(f < fmin){
58 fmin = f;
59 vga->d[0] = d;
60 vga->n[0] = n;
61 vga->p[0] = p;
62 }
63 }
64 }
65 }
66
67 ctlr->flag |= Finit;
68 }
69
70 Ctlr tvp3025clock = {
71 "tvp3025clock", /* name */
72 0, /* snarf */
73 0, /* options */
74 init, /* init */
75 0, /* load */
76 0, /* dump */
77 };
78