xref: /plan9/sys/src/cmd/aux/vga/ch9294.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 /*
2  * Chrontel
3  * CH9294 Dual Enhanced Graphics Clock Generator.
4  */
5 #include <u.h>
6 #include <libc.h>
7 #include <bio.h>
8 
9 #include "pci.h"
10 #include "vga.h"
11 
12 typedef struct {
13 	char*	name[2];
14 	ulong	frequency[16];
15 } Pattern;
16 
17 static Pattern patterns[] = {
18 	{ "e", "E",		/* Tseng */
19 	 50350000,  56644000,  65000000,  72000000,  80000000,  89800000,  63000000,  75000000,
20 	 VgaFreq0,  VgaFreq1,  31500000,  36000000,  40000000,  44900000,  50000000,  65000000,
21 	},
22 	{ "g", "G",		/* S3, IIT */
23 	 VgaFreq0,  VgaFreq1,  40000000,  72000000,  50000000,  77000000,  36000000,  44900000,
24 	130000000, 120000000,  80000000,  31500000, 110000000,  65000000,  75000000,  94500000,
25 	},
26 	{ "k", "K",		/* Avance Logic */
27 	 50350000,  56644000,  89800000,  72000000,  75000000,  65000000,  63000000,  80000000,
28 	 57272000,  85000000,  94000000,  96000000, 100000000, 108000000, 110000000,  77000000,
29 	},
30 
31 	{ 0,
32 	},
33 };
34 
35 static void
init(Vga * vga,Ctlr * ctlr)36 init(Vga* vga, Ctlr* ctlr)
37 {
38 	Pattern *pattern;
39 	char *p;
40 	int f, fmin, index, divisor, maxdivisor;
41 
42 	if(ctlr->flag & Finit)
43 		return;
44 
45 	if(vga->f[0] == 0)
46 		vga->f[0] = vga->mode->frequency;
47 
48 	if((p = strchr(ctlr->name, '-')) == 0)
49 		error("%s: unknown pattern\n", ctlr->name);
50 	p++;
51 
52 	for(pattern = patterns; pattern->name[0]; pattern++){
53 		if(strcmp(pattern->name[0], p) == 0)
54 			break;
55 		if(pattern->name[1] && strcmp(pattern->name[1], p) == 0)
56 			break;
57 	}
58 	if(pattern->name[0] == 0)
59 		error("%s: unknown pattern\n", ctlr->name);
60 
61 	maxdivisor = 1;
62 	if(vga->ctlr && (vga->ctlr->flag & Hclkdiv))
63 		maxdivisor = 8;
64 	fmin = vga->f[0];
65 	for(index = 0; index < 16; index++){
66 		for(divisor = 1; divisor <= maxdivisor; divisor <<= 1){
67 			f = vga->f[0] - pattern->frequency[index]/divisor;
68 			if(f < 0)
69 				f = -f;
70 			if(f < fmin){
71 				/*vga->f = pattern->frequency[index];*/
72 				fmin = f;
73 				vga->d[0] = divisor;
74 				vga->i[0] = index;
75 			}
76 		}
77 	}
78 
79 	if(fmin > (vga->f[0]*5)/100)
80 		error("%s: can't find frequency %ld\n", ctlr->name, vga->f[0]);
81 	ctlr->flag |= Finit;
82 }
83 
84 Ctlr ch9294 = {
85 	"ch9294",			/* name */
86 	0,				/* snarf */
87 	0,				/* options */
88 	init,				/* init */
89 	0,				/* load */
90 	0,				/* dump */
91 };
92