Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
};