xref: /plan9/sys/src/cmd/aux/vga/ch9294.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1219b2ee8SDavid du Colombier /*
2219b2ee8SDavid du Colombier  * Chrontel
3219b2ee8SDavid du Colombier  * CH9294 Dual Enhanced Graphics Clock Generator.
4219b2ee8SDavid du Colombier  */
5219b2ee8SDavid du Colombier #include <u.h>
6219b2ee8SDavid du Colombier #include <libc.h>
77dd7cddfSDavid du Colombier #include <bio.h>
8219b2ee8SDavid du Colombier 
9*9a747e4fSDavid du Colombier #include "pci.h"
10219b2ee8SDavid du Colombier #include "vga.h"
11219b2ee8SDavid du Colombier 
12219b2ee8SDavid du Colombier typedef struct {
13219b2ee8SDavid du Colombier 	char*	name[2];
14219b2ee8SDavid du Colombier 	ulong	frequency[16];
15219b2ee8SDavid du Colombier } Pattern;
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier static Pattern patterns[] = {
187dd7cddfSDavid du Colombier 	{ "e", "E",		/* Tseng */
197dd7cddfSDavid du Colombier 	 50350000,  56644000,  65000000,  72000000,  80000000,  89800000,  63000000,  75000000,
207dd7cddfSDavid du Colombier 	 VgaFreq0,  VgaFreq1,  31500000,  36000000,  40000000,  44900000,  50000000,  65000000,
217dd7cddfSDavid du Colombier 	},
227dd7cddfSDavid du Colombier 	{ "g", "G",		/* S3, IIT */
237dd7cddfSDavid du Colombier 	 VgaFreq0,  VgaFreq1,  40000000,  72000000,  50000000,  77000000,  36000000,  44900000,
24219b2ee8SDavid du Colombier 	130000000, 120000000,  80000000,  31500000, 110000000,  65000000,  75000000,  94500000,
25219b2ee8SDavid du Colombier 	},
267dd7cddfSDavid du Colombier 	{ "k", "K",		/* Avance Logic */
277dd7cddfSDavid du Colombier 	 50350000,  56644000,  89800000,  72000000,  75000000,  65000000,  63000000,  80000000,
287dd7cddfSDavid du Colombier 	 57272000,  85000000,  94000000,  96000000, 100000000, 108000000, 110000000,  77000000,
297dd7cddfSDavid du Colombier 	},
30219b2ee8SDavid du Colombier 
31219b2ee8SDavid du Colombier 	{ 0,
32219b2ee8SDavid du Colombier 	},
33219b2ee8SDavid du Colombier };
34219b2ee8SDavid du Colombier 
35219b2ee8SDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)36219b2ee8SDavid du Colombier init(Vga* vga, Ctlr* ctlr)
37219b2ee8SDavid du Colombier {
38219b2ee8SDavid du Colombier 	Pattern *pattern;
39219b2ee8SDavid du Colombier 	char *p;
407dd7cddfSDavid du Colombier 	int f, fmin, index, divisor, maxdivisor;
41219b2ee8SDavid du Colombier 
42219b2ee8SDavid du Colombier 	if(ctlr->flag & Finit)
43219b2ee8SDavid du Colombier 		return;
44219b2ee8SDavid du Colombier 
457dd7cddfSDavid du Colombier 	if(vga->f[0] == 0)
467dd7cddfSDavid du Colombier 		vga->f[0] = vga->mode->frequency;
47219b2ee8SDavid du Colombier 
48219b2ee8SDavid du Colombier 	if((p = strchr(ctlr->name, '-')) == 0)
49219b2ee8SDavid du Colombier 		error("%s: unknown pattern\n", ctlr->name);
50219b2ee8SDavid du Colombier 	p++;
51219b2ee8SDavid du Colombier 
52219b2ee8SDavid du Colombier 	for(pattern = patterns; pattern->name[0]; pattern++){
53219b2ee8SDavid du Colombier 		if(strcmp(pattern->name[0], p) == 0)
54219b2ee8SDavid du Colombier 			break;
55219b2ee8SDavid du Colombier 		if(pattern->name[1] && strcmp(pattern->name[1], p) == 0)
56219b2ee8SDavid du Colombier 			break;
57219b2ee8SDavid du Colombier 	}
58219b2ee8SDavid du Colombier 	if(pattern->name[0] == 0)
59219b2ee8SDavid du Colombier 		error("%s: unknown pattern\n", ctlr->name);
60219b2ee8SDavid du Colombier 
617dd7cddfSDavid du Colombier 	maxdivisor = 1;
627dd7cddfSDavid du Colombier 	if(vga->ctlr && (vga->ctlr->flag & Hclkdiv))
637dd7cddfSDavid du Colombier 		maxdivisor = 8;
647dd7cddfSDavid du Colombier 	fmin = vga->f[0];
65219b2ee8SDavid du Colombier 	for(index = 0; index < 16; index++){
667dd7cddfSDavid du Colombier 		for(divisor = 1; divisor <= maxdivisor; divisor <<= 1){
677dd7cddfSDavid du Colombier 			f = vga->f[0] - pattern->frequency[index]/divisor;
68219b2ee8SDavid du Colombier 			if(f < 0)
69219b2ee8SDavid du Colombier 				f = -f;
707dd7cddfSDavid du Colombier 			if(f < fmin){
717dd7cddfSDavid du Colombier 				/*vga->f = pattern->frequency[index];*/
727dd7cddfSDavid du Colombier 				fmin = f;
737dd7cddfSDavid du Colombier 				vga->d[0] = divisor;
747dd7cddfSDavid du Colombier 				vga->i[0] = index;
757dd7cddfSDavid du Colombier 			}
767dd7cddfSDavid du Colombier 		}
777dd7cddfSDavid du Colombier 	}
78219b2ee8SDavid du Colombier 
797dd7cddfSDavid du Colombier 	if(fmin > (vga->f[0]*5)/100)
807dd7cddfSDavid du Colombier 		error("%s: can't find frequency %ld\n", ctlr->name, vga->f[0]);
81219b2ee8SDavid du Colombier 	ctlr->flag |= Finit;
82219b2ee8SDavid du Colombier }
83219b2ee8SDavid du Colombier 
84219b2ee8SDavid du Colombier Ctlr ch9294 = {
85219b2ee8SDavid du Colombier 	"ch9294",			/* name */
86219b2ee8SDavid du Colombier 	0,				/* snarf */
87219b2ee8SDavid du Colombier 	0,				/* options */
88219b2ee8SDavid du Colombier 	init,				/* init */
89219b2ee8SDavid du Colombier 	0,				/* load */
90219b2ee8SDavid du Colombier 	0,				/* dump */
91219b2ee8SDavid du Colombier };
92