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)/10) /* could be /10 */
9
10 static void
init(Vga * vga,Ctlr * ctlr)11 init(Vga* vga, Ctlr* ctlr)
12 {
13 int f, k;
14 ulong fmin, fvco, m, n, p, q;
15 double z;
16
17 if(ctlr->flag & Finit)
18 return;
19
20 if(vga->f[0] == 0)
21 vga->f[0] = vga->mode->frequency;
22 vga->misc &= ~0x0C;
23 if(vga->f[0] == VgaFreq0){
24 /* nothing to do */;
25 }
26 else if(vga->f[0] == VgaFreq1)
27 vga->misc |= 0x04;
28 else
29 vga->misc |= 0x0C;
30
31 /*
32 * Look for values of n, d and p that give
33 * the least error for
34 * Fvco = 8*RefFreq*(65-m)/(65-n)
35 * Fpll = Fvco/2**p
36 * N and m are 6 bits, p is 2 bits. Constraints:
37 * 110MHz <= Fvco <= 250MHz
38 * 40 <= n <= 62
39 * 1 <= m <= 62
40 * 0 <= p <= 3
41 * Should try to minimise n, m.
42 *
43 * There's nothing like brute force and ignorance.
44 */
45 fmin = vga->f[0];
46 vga->m[0] = 0x15;
47 vga->n[0] = 0x18;
48 vga->p[0] = 3;
49 for(m = 62; m > 0; m--){
50 for(n = 62; n >= 40; n--){
51 fvco = 8*SCALE(RefFreq)*(65-m)/(65-n);
52 if(fvco < SCALE(110000000) || fvco > SCALE(250000000))
53 continue;
54 for(p = 0; p < 4; p++){
55 f = SCALE(vga->f[0]) - (fvco>>p);
56 if(f < 0)
57 f = -f;
58 if(f < fmin){
59 fmin = f;
60 vga->m[0] = m;
61 vga->n[0] = n;
62 vga->p[0] = p;
63 }
64 }
65 }
66 }
67
68 /*
69 * Now the loop clock:
70 * m is fixed;
71 * calculate n;
72 * set z to the lower bound (110MHz) and calculate p and q.
73 */
74 vga->m[1] = 61;
75 if(ctlr->flag & Uenhanced)
76 k = 64/8;
77 else
78 k = 8/8;
79 n = 65 - 4*k;
80 fvco = (8*RefFreq*(65-vga->m[0]))/(65-vga->n[0]);
81 vga->f[1] = fvco;
82 z = 110.0*(65-n)/(4*(fvco/1000000.0)*k);
83 if(z <= 16){
84 for(p = 0; p < 4; p++){
85 if(1<<(p+1) > z)
86 break;
87 }
88 q = 0;
89 }
90 else{
91 p = 3;
92 q = (z - 16)/16 + 1;
93 }
94 vga->n[1] = n;
95 vga->p[1] = p;
96 vga->q[1] = q;
97
98 ctlr->flag |= Finit;
99 }
100
101 Ctlr tvp3026clock = {
102 "tvp3026clock", /* name */
103 0, /* snarf */
104 0, /* options */
105 init, /* init */
106 0, /* load */
107 0, /* dump */
108 };
109