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)/1)		/* could be /10 */
9
 
10
static void
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
};