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