]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/i81x.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / aux / vga / i81x.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 /*
9  * Intel 81x chipset family.
10  *   mem[0]: AGP aperture memory, 64MB for 810-DC100, from 0xF4000000
11  *   mem[1]: GC Register mmio space, 512KB for 810-DC100, from 0xFF000000
12  *   For the memory of David Hogan, died April 9, 2003,  who wrote this driver 
13  *   first for LCD.
14  *                   August 28, 2003 Kenji Okamoto
15  */
16
17 typedef struct {
18         Pcidev* pci;
19         uchar*  mmio;
20         ulong   clk[6];
21         ulong   lcd[9];
22         ulong   pixconf;
23 } I81x;
24
25 static void
26 snarf(Vga* vga, Ctlr* ctlr)
27 {
28         int i;
29         uchar *mmio;
30         ulong *rp;
31         Pcidev *p;
32         I81x *i81x;
33
34         if(vga->private == nil){
35                 vga->private = alloc(sizeof(I81x));
36                 p = vga->pci;
37                 if(p == nil){
38                         while((p = pcimatch(p, 0x8086, 0)) != nil) {
39                                 switch(p->did) {
40                                 default:
41                                         continue;
42                                 case 0x7121:    /* Vanilla 82810 */
43                                 case 0x7123:    /* 810-DC100, DELL OptiPlex GX100 */
44                                 case 0x7125:    /* 82810E */
45                                 case 0x1102:    /* 82815 FSB limited to 100MHz */
46                                 case 0x1112:    /* 82815 no AGP */
47                                 case 0x1132:    /* 82815 fully featured Solano */
48                                 case 0x3577:    /* IBM R31 uses intel 830M chipset */
49                                         break;
50                                 }
51                                 break;
52                         }
53                         if(p == nil)
54                                 error("%s: Intel 81x graphics function not found\n", ctlr->name);
55                 }
56                 vga->f[1] = 230000000;          /* MAX speed of internal DAC (Hz)*/
57
58                 vgactlpci(p);
59                 vgactlw("type", "i81x");
60
61                 mmio = segattach(0, "i81xmmio", 0, p->mem[1].size);
62                 if(mmio == (void*)-1)
63                         error("%s: can't attach mmio segment\n", ctlr->name);
64         
65                 i81x = vga->private;
66                 i81x->pci = p;
67                 i81x->mmio = mmio;
68         }
69         i81x = vga->private;
70
71         /* must give aperture memory size for frame buffer memory
72                 such as 64*1024*1024 */
73         vga->vma = vga->vmz = i81x->pci->mem[0].size;
74 //      vga->vmz = 8*1024*1024;
75         vga->apz = i81x->pci->mem[0].size;
76         ctlr->flag |= Hlinear;
77
78         vga->graphics[0x10] = vgaxi(Grx, 0x10);
79         vga->attribute[0x11] = vgaxi(Attrx, 0x11);      /* overscan color */
80         for(i=0; i < 0x19; i++)
81                 vga->crt[i] = vgaxi(Crtx, i);
82         for(i=0x30; i <= 0x82; i++)             /* set CRT Controller Register (CR) */
83                 vga->crt[i] = vgaxi(Crtx, i);
84         /* 0x06000: Clock Control Register base address (3 VCO frequency control) */
85         rp = (ulong*)(i81x->mmio+0x06000);
86         for(i = 0; i < nelem(i81x->clk); i++)
87                 i81x->clk[i] = *rp++;
88
89         /* i830 CRTC registers (A) */
90         rp = (ulong*)(i81x->mmio+0x60000);
91         for(i = 0; i < nelem(i81x->lcd); i++)
92                 i81x->lcd[i] = *rp++;
93         rp = (ulong*)(i81x->mmio+0x70008);      /* Pixel Pipeline Control register A */
94         i81x->pixconf = *rp;
95
96         ctlr->flag |= Fsnarf;
97 }
98
99 static void
100 options(Vga*, Ctlr* ctlr)
101 {
102         ctlr->flag |= Hlinear|Foptions;
103 }
104
105 static void
106 i81xdclk(I81x *i81x, Vga *vga)          /* freq = MHz */
107 {
108         int m, n, post, mtp, ntp;
109         double md, freq, error;
110
111         freq = vga->mode->deffrequency/1000000.0;
112         if (freq == 0)
113                 sysfatal("i81xdclk: deffrequency %d becomes freq 0.0",
114                         vga->mode->deffrequency);
115         post = log(600.0/freq)/log(2.0);
116
117         for(ntp=3;;ntp++) {
118                 md = freq*(1<<post)/(24.0/(double)ntp)/4.0;
119                 mtp = (int)(md+0.5);
120                 if(mtp<3) mtp=3;
121                 error = 1.0-freq/(md/(ntp*(1<<post))*4*24.0);
122                 if((fabs(error) < 0.001) || ((ntp > 30) && (fabs(error) < 0.005)))
123                         break;
124         }
125         m = vga->m[1] = mtp-2;
126         n = vga->n[1] = ntp-2;
127         vga->r[1] = post;
128         i81x->clk[2] = ((n & 0x3FF)<<16) | (m & 0x3FF);
129         i81x->clk[4] = (i81x->clk[4] & ~0x700000) | ((post & 0x07)<<20);
130         vga->mode->frequency = (m+2)/((n+2)*(1<<post))*4*24*1000000;
131 }
132
133 static void
134 init(Vga* vga, Ctlr* ctlr)
135 {
136         I81x *i81x;
137         int vt, vde, vrs, vre;
138         ulong *rp;
139
140         i81x = vga->private;
141
142         /* <<TODO>>
143             i81x->clk[3]: LCD_CLKD: 0x0600c~0x0600f, default=00030013h
144                         (VCO N-divisor=03h, M-divisor=13h)
145             i81x->clk[4]: DCLK_0DS: 0x06010~0x06013, Post value, default=40404040h means
146                 Post Divisor=16, VCO Loop divisor = 4xM for all clocks.
147             Display&LCD Clock Devisor Select Reg = 0x40404040 ==> (LCD)(Clock2)(Clock1)(Clock0)
148         */
149         i81x->clk[0] = 0x00030013;
150         i81x->clk[1] = 0x00100053;
151         rp = (ulong*)i81x->mmio+0x6010;
152         i81x->clk[4] = *rp;
153         i81x->clk[4] |= 0x4040;
154         vga->misc = vgai(MiscR);
155         switch(vga->virtx) {
156         case 640:       /* 640x480 DCLK_0D 25.175MHz dot clock */
157                 vga->misc &=  ~0x0A;
158                 break;
159         case 720:       /* 720x480 DCLK_1D 28.322MHz dot clock */
160                 vga->misc = (vga->misc & ~0x08) | (1<<2);
161                 break;
162         case 800:
163         case 1024:
164         case 1152:
165         case 1280:
166         case 1376:
167                 vga->misc = vga->misc | (2<<2) & ~0x02;         /* prohibit to access frame buffer */
168                 i81xdclk(i81x, vga);
169                 break;
170         default:        /* for other higher resolution DCLK_2D */
171                 error("%s: Only 800, 1024, 1152, 1280, 1376 resolutions are supported\n", ctlr->name);
172         }
173
174         /*      <<TODO>>
175                 i830 LCD Controller, at i81x->mmio+0x60000
176                 i81x->lcd[0]: Horizontal Total Reg.             0x60000
177                 i81x->lcd[1]: Horizontal Blanking Reg.  0x60004
178                 i81x->lcd[2]: Horizontal Sync Reg.              0x60008
179                 i81x->lcd[3]: Vertical Total Reg.               0x6000c
180                 i81x->lcd[4]: Vertical Blanking Reg.            0x60010
181                 i81x->lcd[5]: Vertical Sync Reg.                0x60014
182                 i81x->lcd[6]: Pixel Pipeline A Sequencer Register Control(SRC,0~7)      0x6001c
183                 i81x->lcd[7]: BCLRPAT_A 0x60020
184                  i81x->lcd[8]: 0
185         */
186         /*
187          * Pixel pipeline control register 0x70008: 
188          *    16/24bp bypasses palette,
189          *    hw cursor enabled(1<<12), hi-res mode(1<<0), depth(16-19 bit)
190          *    8bit DAC enable (1<<15), don't wrap to 256kM memory of VGA(1<<1).
191          *    enable extended palette addressing (1<<8)
192         */
193         i81x->pixconf = (1<<12)|(1<<0);
194         i81x->pixconf &= 0xFFFFFBFF;    /* disable overscan color */
195         switch(vga->mode->z) {          /* vga->mode->z: color depth */
196         case 8:
197                 i81x->pixconf |= (2<<16);
198                 break;
199         case 16:        /* (5:6:5 bit) */
200                 i81x->pixconf |= (5<<16);
201                 break;
202         case 24:
203                 i81x->pixconf |= (6<<16);
204                 break;
205         case 32:                /* not supported */
206                 i81x->pixconf |= (7<<16);
207                 break;
208         default:
209                 error("%s: depth %d not supported\n", ctlr->name, vga->mode->z);
210         }
211
212         /* DON'T CARE of Sequencer Reg. */
213         /* DON'T CARE of Attribute registers other than this */
214         vga->attribute[0x11] = 0;               /* over scancolor = black */
215         /* DON't CARE of graphics[1], [2], [3], [4], [5], [6], [7] and [8] value */
216         if(vga->linear && (ctlr->flag & Hlinear)) {
217         /* enable linear mapping, no VGA memory and no page mapping */
218                 vga->graphics[0x10] = 0x0A;
219                 ctlr->flag |= Ulinear;
220         }
221
222         vt = vga->mode->vt;
223         vde = vga->virty;
224         vrs = vga->mode->vrs;
225         vre = vga->mode->vre+6;         /* shift 7 pixel up */
226
227         if(vga->mode->interlace == 'v') {
228                 vt /= 2;
229                 vde /= 2;
230                 vrs /= 2;
231                 vre /= 2;
232         }
233                 /* Reset Row scan */
234         vga->crt[8] = 0;
235 /* Line Compare, bit 6 of crt[9], bit 4 of crt[7] and crt[0x18], should be
236  *      vga->crt[9] = vgaxi(Crtx, 9) | ((vde>>9 & 1)<<6) & 0x7F;
237  *      vga->crt[7] = vgaxi(Crtx, 7) | ((vde>>8 & 1)<<4);
238  *      vga->crt[0x18] = vde & 0xFF;
239  *      However, above values don't work!!  I don't know why.   K.Okamoto
240  */
241         vga->crt[9] = 0;                /* I don't know why ? */
242         vga->crt[7] = 0;                /* I don't know why ? */
243         vga->crt[0x18] = 0;             /* I don't know why ? */
244 /*      32 bits Start Address of frame buffer (AGP aperture memory)
245         vga->crt[0x42] = MSB 8 bits of Start Address Register, extended high start address Reg.
246         vga->crt[0x40] = higer 6 bits in 0~5 bits, and the MSB = 1, extebded start address Reg.
247         vga->crt[0x0C] = Start Address High Register
248         vga->crt[0x0D] = Start Address Low Register
249         LSB 2 bits of Start Address are always 0
250  */
251         vga->crt[0x42] = vga->pci->mem[0].bar>>24 & 0xFF;
252         vga->crt[0x40] = vga->pci->mem[0].bar>>18 & 0x3F | 0x80;
253                 /* Start Address High */
254         vga->crt[0x0C] = vga->pci->mem[0].bar>>10 & 0xFF;
255                 /* Start Address Low */
256         vga->crt[0x0D] = (vga->pci->mem[0].bar >>2 + 1)& 0xFF;
257                 /* Underline Location, Memory Mode, DON'T CARE THIS VALUE */
258         vga->crt[0x14] = 0x0;
259                 /* CRT Mode Control */
260         vga->crt[0x17] = 0x80;          /* CRT normal mode */
261                 /* Frame buffer memory offset  (memory amount for a line) */
262                 /* vga->crt[0x13] = lower 8 bits of Offset Register
263                         vga->crt[0x41] = MSB 4 bits, those value should be
264                         vga->crt[0x13] = (vga->virtx*(vga->mode->z>>3)/4) & 0xFF;
265                         vga->crt[0x41] = (vga->virtx*(vga->mode->z>>3)/4)>>8 & 0x0F;
266                   However, those doesn't work properly  K.Okamoto
267                 */
268         vga->crt[0x41] = (vga->crt[0x13]>>8) & 0x0F;            //dhog
269
270                 /* Horizontal Total */
271         vga->crt[0] = ((vga->mode->ht>>3)-6) & 0xFF;
272                 /* Extended Horizontal Total Time Reg (ht)  */
273         vga->crt[0x35] = vga->mode->ht>>12 & 0x01;
274 //      vga->crt[0x35] = (((vga->mode->ht>>1)-5)>>8) & 0x01;    //dhog
275                 /* Horizontal Display Enable End == horizontal width */
276         vga->crt[1] = (vga->virtx-1)>>3 & 0xFF;
277                 /* Horizontal Blanking Start */
278         vga->crt[2] = ((vga->mode->shb>>3)-1) & 0xFF;
279                 /* Horizontal blanking End crt[39](0),crt[5](7),crt[3](4:0) */
280         vga->crt[3] = (vga->mode->shb - vga->virtx)>>3 & 0x1F;
281         vga->crt[5] = ((vga->mode->shb - vga->virtx)>>3 & 0x20) <<2;
282         vga->crt[0x39] = ((vga->mode->shb - vga->virtx)>>3 & 0x40) >>6;
283 //      vga->crt[0x39] = (vga->mode->ehb>>9) & 0x01;            //dhog
284                 /* Horizontal Sync Start */
285         vga->crt[4] = vga->mode->shb>>3 & 0xFF;
286                 /* Horizontal Sync End */
287         vga->crt[5] |= vga->mode->ehb>>3 & 0x1F;
288                 /* Extended Vertical Total (vt) */
289         vga->crt[6] = (vt - 2) & 0xFF;
290         vga->crt[0x30] = (vt - 2)>>8 & 0x0F;
291                 /* Vertical Sync Period */
292         vga->crt[0x11] = (vre - vrs - 2) & 0x0F;
293                 /* Vertical Blanking End  */
294         vga->crt[0x16] = (vre - vrs) & 0xFF;
295                 /* Extended Vertical Display End (y) */
296         vga->crt[0x12] = (vde-1) & 0xFF;
297         vga->crt[0x31] = (vde-1)>>8 & 0x0f;
298                 /* Extended Vertical Sync Start (vrs)  */
299         vga->crt[0x10] = (vrs-1) & 0xFF;
300         vga->crt[0x32] = (vrs-1)>>8 & 0x0F;
301                 /* Extended Vertical Blanking Start (vrs) */
302         vga->crt[0x15] = vrs & 0xFF;
303         vga->crt[0x33] = vrs>>8 & 0x0F;
304
305         if(vga->mode->interlace == 'v')
306                 vga->crt[0x70] = vrs | 0x80;
307         else
308                 vga->crt[0x70] = 0;
309         vga->crt[0x80] = 1;
310
311         ctlr->flag |= Finit;
312 }
313
314 static void
315 load(Vga* vga, Ctlr* ctlr)
316 {
317         int i;
318         ulong *rp;
319         I81x *i81x;
320         char *p;
321
322         i81x = vga->private;
323
324         vgaxo(Attrx, 0x11, vga->attribute[0x11]);
325         /* set the screen graphic mode */
326         vgaxo(Crtx, 0x80, vga->crt[0x80]);
327         vgaxo(Grx, 0x10, vga->graphics[0x10]);
328         vgao(MiscW, vga->misc);
329         for(i=0; i <= 0x18; i++)
330                 vgaxo(Crtx, i, vga->crt[i]);
331         for(i=0x30; i <= 0x82; i++)
332                 vgaxo(Crtx, i, vga->crt[i]);
333         vga->crt[0x40] |= 0x80;                 /* set CR40, then set the MSB bit of it */
334         vgaxo(Crtx, 0x40, vga->crt[0x40]);
335         /* 0x06000 = offset of Vertical Clock Devisor VGA0 */
336         rp = (ulong*)(i81x->mmio+0x06000);
337         for(i=0; i < nelem(i81x->clk); i++)
338                 *rp++ = i81x->clk[i];
339         rp = (ulong*)(i81x->mmio+0x60000);
340         for(i = 0; i < nelem(i81x->lcd); i++)
341                 *rp++ = i81x->lcd[i];
342         /* set cursor, graphic mode */
343         rp = (ulong*)(i81x->mmio+0x70008);
344         *rp = i81x->pixconf | (1<<8);
345
346         p = (char*)(i81x->mmio+Pixmask);        /* DACMASK */
347         *p = 0xff;
348         p = (char*)(i81x->mmio+PaddrW);         /* DACWX */
349         *p = 0x04;
350         p = (char*)(i81x->mmio+Pdata);          /* DACDATA */
351         *p = 0xff;
352         *p = 0xff;
353         *p = 0xff;
354         *p = 0x00;
355         *p = 0x00;
356         *p = 0x00;
357         *rp = i81x->pixconf;
358
359         ctlr->flag |= Fload;
360 }
361
362 static void
363 dump(Vga* vga, Ctlr* ctlr)
364 {
365         int i;
366         Pcidev *p;
367         I81x *i81x;
368         char *name;
369
370         name = ctlr->name;
371         i81x = vga->private;
372
373         printitem(name, "Crt30");
374         for(i = 0x30; i <= 0x39; i++)
375                 printreg(vga->crt[i]);
376
377         printitem(name, "Crt40");
378         for(i = 0x40; i <= 0x42; i++)
379                 printreg(vga->crt[i]);
380
381         printitem(name, "Crt70");
382         for(i = 0x70; i <= 0x79; i++)
383                 printreg(vga->crt[i]);
384
385         printitem(name, "Crt80");
386         for(i = 0x80; i <= 0x82; i++)
387                 printreg(vga->crt[i]);
388
389         printitem(name, "Graphics10");
390         for(i = 0x10; i <= 0x1f; i++)
391                 printreg(vga->graphics[i]);
392
393         printitem(name, "clk");
394         for(i = 0; i < nelem(i81x->clk); i++)
395                 printreg(i81x->clk[i]);
396
397         printitem(name, "lcd");
398         for(i = 0; i < nelem(i81x->lcd); i++)
399                 printreg(i81x->lcd[i]);
400
401         printitem(name, "pixconf");
402         printreg(i81x->pixconf);
403
404         p = i81x->pci;
405         printitem(name, "mem[0]");
406         Bprint(&stdout, "base %lux size %d\n", p->mem[0].bar & ~0x0F, p->mem[0].size);
407
408         printitem(name, "mem[1]");
409         Bprint(&stdout, "base %lux size %d\n", p->mem[1].bar & ~0x0F, p->mem[1].size);
410
411 }
412
413 Ctlr i81x = {
414         "i81x",                 /* name */
415         snarf,                          /* snarf */
416         options,                        /* options */
417         init,                           /* init */
418         load,                           /* load */
419         dump,                           /* dump */
420 };
421
422 Ctlr i81xhwgc = {
423         "i81xhwgc",                     /* name */
424         0,                              /* snarf */
425         0,                              /* options */
426         0,                              /* init */
427         0,                              /* load */
428         0,                              /* dump */
429 };