xref: /plan9/sys/src/cmd/aux/vga/neomagic.c (revision 5b7f163ef926031138d13ab99fb6fc8ce599f427)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 
8 typedef struct {
9 	Pcidev*	pci;
10 
11 	int	x;
12 	int	y;
13 } Neomagic;
14 
15 enum {
16 	ExtCrtx = 0x19,
17 	MaxCRT=0x85,
18 	MaxGR=0xc7,
19 };
20 
21 enum {
22 	GeneralLockReg = 0x0A,
23 	ExtCRTDispAddr = 0x0E,
24 	ExtCRTOffset = 0x0F,
25 	SysIfaceCntl1 = 0x10,
26 	SysIfaceCntl2 = 0x11,
27 	SingleAddrPage = 0x15,		/* not changed? */
28 	DualAddrPage = 0x16,		/* not changed? */
29 	PanelDispCntlReg1 = 0x20,
30 	PanelDispCntlReg2 = 0x25,
31 	PanelDispCntlReg3 = 0x30,
32 	PanelVertCenterReg1 = 0x28,
33 	PanelVertCenterReg2 = 0x29,
34 	PanelVertCenterReg3 = 0x2A,
35 	PanelVertCenterReg4 = 0x32,	/* not 2070 */
36 	PanelHorizCenterReg1 = 0x33,
37 	PanelHorizCenterReg2 = 0x34,
38 	PanelHorizCenterReg3 = 0x35,
39 	PanelHorizCenterReg4 = 0x36,	/* 2160, 2200, 2360 */
40 	PanelVertCenterReg5 = 0x37,	/* 2200, 2360 */
41 	PanelHorizCenterReg5 = 0x38,	/* 2200, 2360 */
42 
43 	ExtColorModeSelect = 0x90,
44 
45 	VerticalExt = 0x70,		/* 2200; iobase+4 */
46 };
47 
48 static int crts[] = {
49 	0x1D, 0x1F, 0x21, 0x23, 0x25, 0x2F,
50 	/* also 40-59, 60-69, 70-MaxCRT */
51 	-1
52 };
53 
54 /*
55  * Neomagic driver (fake)
56  */
57 static void
snarf(Vga * vga,Ctlr * ctlr)58 snarf(Vga* vga, Ctlr* ctlr)
59 {
60 	int i;
61 	Pcidev *p;
62 	Neomagic *nm;
63 
64 	generic.snarf(vga, ctlr);
65 
66 	outportw(Grx, 0x2609);	/* unlock neo registers */
67 	outportw(Grx, 0x0015);	/* reset bank */
68 
69 	for(i=0; crts[i] >= 0; i++)
70 		vga->crt[crts[i]] = vgaxi(Crtx, crts[i]);
71 	for(i=0x40; i <= MaxCRT; i++)
72 		vga->crt[i] = vgaxi(Crtx, i);
73 
74 	for(i=0x08; i<=0x3F; i++)
75 		vga->graphics[i] = vgaxi(Grx, i);
76 	for(i=0x70; i<=MaxGR; i++)
77 		vga->graphics[i] = vgaxi(Grx, i);
78 
79 	if(vga->private == nil){
80 		vga->private = alloc(sizeof(Neomagic));
81 		nm = vga->private;
82 		if((p = pcimatch(0, 0x10C8, 0)) == nil)
83 			error("%s: not found\n", ctlr->name);
84 		switch(p->did){
85 		case 0x0003:			/* MagicGraph 128 ZV */
86 			vga->f[1] = 80000000;
87 			vga->vmz = 2048*1024;
88 			vga->apz = 4*1024*1024;
89 			break;
90 		case 0x0083:			/* MagicGraph 128 ZV+ */
91 			vga->f[1] = 80000000;
92 			vga->vmz = 2048*1024;
93 			vga->apz = 4*1024*1024;
94 			break;
95 		case 0x0004:			/* MagicGraph 128 XD */
96 			vga->f[1] = 90000000;
97 			vga->vmz = 2048*1024;
98 			vga->apz = 16*1024*1024;
99 			break;
100 		case 0x0005:			/* MagicMedia 256 AV */
101 			vga->f[1] = 110000000;
102 			vga->vmz = 2560*1024;
103 			vga->apz = 16*1024*1024;
104 			break;
105 		case 0x0006:			/* MagicMedia 256 ZX */
106 			vga->f[1] = 110000000;
107 			vga->vmz = 4096*1024;
108 			vga->apz = 16*1024*1024;
109 			break;
110 		case 0x0016:			/* MagicMedia 256 XL+ */
111 			vga->f[1] = 110000000;
112 			/* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
113 			vga->vmz = 4096*1024;
114 			vga->apz = 32*1024*1024;
115 			break;
116 		case 0x0001:			/* MagicGraph 128 */
117 		case 0x0002:			/* MagicGraph 128 V */
118 		default:
119 			error("%s: DID %4.4uX unsupported\n",
120 				ctlr->name, p->did);
121 		}
122 		nm->pci = p;
123 	}
124 
125 	ctlr->flag |= Fsnarf;
126 }
127 
128 static void
options(Vga *,Ctlr * ctlr)129 options(Vga*, Ctlr* ctlr)
130 {
131 	ctlr->flag |= Ulinear|Hlinear|Foptions;
132 }
133 
134 static void
init(Vga * vga,Ctlr * ctlr)135 init(Vga* vga, Ctlr* ctlr)
136 {
137 	Neomagic *nm;
138 	int i, h, v, t;
139 
140 	generic.init(vga, ctlr);
141 
142 	nm = vga->private;
143 	switch((vga->graphics[0x20]>>3)&3){
144 	case 0:
145 		nm->x = 640;
146 		nm->y = 480;
147 		break;
148 	case 1:
149 		nm->x = 800;
150 		nm->y = 600;
151 		break;
152 	case 2:
153 		nm->x = 1024;
154 		nm->y = 768;
155 	case 3:
156 		nm->x = 1280;
157 		nm->y = 1024;
158 		break;
159 	}
160 
161 	vga->crt[0x0C] = 0;	/* vga starting address (offset) */
162 	vga->crt[0x0D] = 0;
163 	vga->graphics[GeneralLockReg] = 0x01;	/* (internal or simultaneous) */
164 	vga->attribute[0x10] &= ~0x40;	/* 2x4 mode not right for neomagic */
165 
166 	t = 2;		/* LCD only (0x01 for external) */
167 	switch(vga->mode->x){
168 	case 1280:
169 		t |= 0x60;
170 		break;
171 	case 1024:
172 		t |= 0x40;
173 		break;
174 	case 800:
175 		t |= 0x20;
176 		break;
177 	}
178 	if(0 && (nm->pci->did == 0x0005) || (nm->pci->did == 0x0006)){
179 		vga->graphics[PanelDispCntlReg1] &= 0x98;
180 		vga->graphics[PanelDispCntlReg1] |= (t & ~0x98);
181 	}
182 	else{
183 		vga->graphics[PanelDispCntlReg1] &= 0xDC;	/* save bits 7:6, 4:2 */
184 		vga->graphics[PanelDispCntlReg1] |= (t & ~0xDC);
185 	}
186 
187 	vga->graphics[PanelDispCntlReg2] &= 0x38;
188 	vga->graphics[PanelDispCntlReg3] &= 0xEF;
189 	vga->graphics[PanelVertCenterReg1] = 0x00;
190 	vga->graphics[PanelVertCenterReg2] = 0x00;
191 	vga->graphics[PanelVertCenterReg3] = 0x00;
192 	vga->graphics[PanelVertCenterReg4] = 0x00;
193 	vga->graphics[PanelVertCenterReg5] = 0x00;
194 	vga->graphics[PanelHorizCenterReg1] = 0x00;
195 	vga->graphics[PanelHorizCenterReg2] = 0x00;
196 	vga->graphics[PanelHorizCenterReg3] = 0x00;
197 	vga->graphics[PanelHorizCenterReg4] = 0x00;
198 	vga->graphics[PanelHorizCenterReg5] = 0x00;
199 	if(vga->mode->x < nm->x){
200 		vga->graphics[PanelDispCntlReg2] |= 0x01;
201 		vga->graphics[PanelDispCntlReg3] |= 0x10;
202 		h = ((nm->x - vga->mode->x) >> 4) - 1;
203 		v = ((nm->y - vga->mode->y) >> 1) - 2;
204 		switch(vga->mode->x){
205 		case 640:
206 			vga->graphics[PanelHorizCenterReg1] = h;
207 			vga->graphics[PanelVertCenterReg3] = v;
208 			break;
209 		case 800:
210 			vga->graphics[PanelHorizCenterReg2] = h;
211 			vga->graphics[PanelVertCenterReg4] = v;
212 			break;
213 		case 1024:
214 			vga->graphics[PanelHorizCenterReg5] = h;
215 			vga->graphics[PanelVertCenterReg5] = v;
216 			break;
217 		}
218 	}
219 
220 	vga->graphics[ExtCRTDispAddr] = 0x10;
221 	vga->graphics[SysIfaceCntl1] &= 0x0F;
222 	vga->graphics[SysIfaceCntl1] |= 0x30;
223 	vga->graphics[SysIfaceCntl2] = 0x40;	/* make sure MMIO is enabled */
224 	vga->graphics[SingleAddrPage] = 0x00;
225 	vga->graphics[DualAddrPage] = 0x00;
226 	vga->graphics[ExtCRTOffset] = 0x00;
227 	t = vga->graphics[ExtColorModeSelect] & 0x70;	/* colour mode extension */
228 	if(vga->mode->z == 8){
229 		t |= 0x11;
230 		vga->crt[0x13] = vga->mode->x/8;
231 		vga->graphics[ExtCRTOffset] = vga->mode->x>>11;
232 		vga->graphics[0x05] = 0x00;	/* linear addressing? */
233 		vga->crt[0x14] = 0x40;	/* double word mode but don't count by 4 */
234 	}
235 	else if(vga->mode->z == 16){
236 		t |= 0x13;
237 		vga->crt[0x13] = vga->mode->x/4;
238 		vga->graphics[0x05] = 0x00;	/* linear addressing? */
239 		vga->crt[0x14] = 0x40;	/* double word mode but don't count by 4 */
240 		vga->graphics[ExtCRTOffset] = vga->mode->x>>10;
241 		for(i = 0; i < Pcolours; i++){
242 			vga->palette[i][Red] = i<<1;
243 			vga->palette[i][Green] = i;
244 			vga->palette[i][Blue] = i<<1;
245 		}
246 	}
247 	else if(vga->mode->z == 24){
248 		t |= 0x14;
249 		vga->crt[0x13] = (vga->mode->x*3)/8;
250 //		vga->graphics[0x05] = 0x00;	/* linear addressing? */
251 		vga->crt[0x14] = 0x40;	/* double word mode but don't count by 4 */
252 		vga->graphics[ExtCRTOffset] = (vga->mode->x*3)>>11;
253 		for(i = 0; i < Pcolours; i++){
254 			vga->palette[i][Red] = i;
255 			vga->palette[i][Green] = i;
256 			vga->palette[i][Blue] = i;
257 		}
258 	}
259 	else
260 		error("depth %d not supported\n", vga->mode->z);
261 	vga->graphics[ExtColorModeSelect] = t;
262 
263 	vga->misc |= 0x0C;
264 
265 	ctlr->flag |= Finit;
266 }
267 
268 static void
load(Vga * vga,Ctlr * ctlr)269 load(Vga* vga, Ctlr* ctlr)
270 {
271 	vgaxo(Grx, GeneralLockReg, vga->graphics[GeneralLockReg]);
272 	vgaxo(Grx, ExtColorModeSelect, vga->graphics[ExtColorModeSelect]);
273 	vgaxo(Grx, PanelDispCntlReg2, vga->graphics[PanelDispCntlReg2] & 0x39);
274 	sleep(200);
275 
276 	generic.load(vga, ctlr);
277 
278 	vgaxo(Grx, ExtCRTDispAddr, vga->graphics[ExtCRTDispAddr]);
279 	vgaxo(Grx, ExtCRTOffset, vga->graphics[ExtCRTOffset] & 0x39);
280 	vgaxo(Grx, SysIfaceCntl1, vga->graphics[SysIfaceCntl1]);
281 	if(ctlr->flag & Ulinear)
282 		vga->graphics[SysIfaceCntl2] |= 0x80;
283 	vgaxo(Grx, SysIfaceCntl2, vga->graphics[SysIfaceCntl2]);
284 	vgaxo(Grx, SingleAddrPage, vga->graphics[SingleAddrPage]);
285 	vgaxo(Grx, DualAddrPage, vga->graphics[DualAddrPage]);
286 	vgaxo(Grx, PanelDispCntlReg1, vga->graphics[PanelDispCntlReg1]);
287 	vgaxo(Grx, PanelDispCntlReg2, vga->graphics[PanelDispCntlReg2]);
288 	vgaxo(Grx, PanelDispCntlReg3, vga->graphics[PanelDispCntlReg3]);
289 	vgaxo(Grx, PanelVertCenterReg1, vga->graphics[PanelVertCenterReg1]);
290 	vgaxo(Grx, PanelVertCenterReg2, vga->graphics[PanelVertCenterReg2]);
291 	vgaxo(Grx, PanelVertCenterReg3, vga->graphics[PanelVertCenterReg3]);
292 	vgaxo(Grx, PanelVertCenterReg4, vga->graphics[PanelVertCenterReg4]);
293 	vgaxo(Grx, PanelHorizCenterReg1, vga->graphics[PanelHorizCenterReg1]);
294 	vgaxo(Grx, PanelHorizCenterReg2, vga->graphics[PanelHorizCenterReg2]);
295 	vgaxo(Grx, PanelHorizCenterReg3, vga->graphics[PanelHorizCenterReg3]);
296 	vgaxo(Grx, PanelHorizCenterReg4, vga->graphics[PanelHorizCenterReg4]);
297 	vgaxo(Grx, PanelVertCenterReg5, vga->graphics[PanelVertCenterReg5]);
298 	vgaxo(Grx, PanelHorizCenterReg5, vga->graphics[PanelHorizCenterReg5]);
299 
300 	if(vga->mode->z != 8)
301 		palette.load(vga, ctlr);
302 }
303 
304 static void
dump(Vga * vga,Ctlr * ctlr)305 dump(Vga* vga, Ctlr* ctlr)
306 {
307 	int i;
308 	char buf[100];
309 
310 	generic.dump(vga, ctlr);
311 
312 	for(i = 0; crts[i] >= 0; i++){
313 		sprint(buf, "Crt%2.2uX", crts[i]);
314 		printitem(ctlr->name, buf);
315 		printreg(vga->crt[crts[i]]);
316 	}
317 	printitem(ctlr->name, "Crt40");
318 	for(i=0x40; i<=0x59; i++)
319 		printreg(vga->crt[i]);
320 	printitem(ctlr->name, "Crt60");
321 	for(i=0x60; i<=0x69; i++)
322 		printreg(vga->crt[i]);
323 	printitem(ctlr->name, "Crt70");
324 	for (i = 0x70; i <= MaxCRT; i++)
325 		printreg(vga->crt[i]);
326 
327 	printitem(ctlr->name, "Gr08");
328 	for(i=0x08; i<=0x3F; i++)
329 		printreg(vga->graphics[i]);
330 	printitem(ctlr->name, "Gr70");
331 	for(i=0x70; i<=MaxGR; i++)
332 		printreg(vga->graphics[i]);
333 }
334 
335 Ctlr neomagic = {
336 	"neomagic",			/* name */
337 	snarf,				/* snarf */
338 	options,			/* options */
339 	init,				/* init */
340 	load,				/* load */
341 	dump,				/* dump */
342 };
343 
344 Ctlr neomagichwgc = {
345 	"neomagichwgc",			/* name */
346 	0,				/* snarf */
347 	0,				/* options */
348 	0,				/* init */
349 	0,				/* load */
350 	0,				/* dump */
351 };
352