1 /*
2  *
3  * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
4  *
5  * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
6  *
7  * Version: 1.51 2001/06/18
8  *
9  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
10  *
11  * Contributors: "menion?" <menion@mindless.com>
12  *                     Betatesting, fixes, ideas
13  *
14  *               "Kurt Garloff" <garloff@suse.de>
15  *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
16  *
17  *               "Tom Rini" <trini@kernel.crashing.org>
18  *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
19  *
20  *               "Bibek Sahu" <scorpio@dodds.net>
21  *                     Access device through readb|w|l and write b|w|l
22  *                     Extensive debugging stuff
23  *
24  *               "Daniel Haun" <haund@usa.net>
25  *                     Testing, hardware cursor fixes
26  *
27  *               "Scott Wood" <sawst46+@pitt.edu>
28  *                     Fixes
29  *
30  *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
31  *                     Betatesting
32  *
33  *               "Kelly French" <targon@hazmat.com>
34  *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
35  *                     Betatesting, bug reporting
36  *
37  *               "Pablo Bianucci" <pbian@pccp.com.ar>
38  *                     Fixes, ideas, betatesting
39  *
40  *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
41  *                     Fixes, enhandcements, ideas, betatesting
42  *
43  *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
44  *                     PPC betatesting, PPC support, backward compatibility
45  *
46  *               "Paul Womar" <Paul@pwomar.demon.co.uk>
47  *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
48  *                     PPC betatesting
49  *
50  *               "Thomas Pornin" <pornin@bolet.ens.fr>
51  *                     Alpha betatesting
52  *
53  *               "Pieter van Leuven" <pvl@iae.nl>
54  *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
55  *                     G100 testing
56  *
57  *               "H. Peter Arvin" <hpa@transmeta.com>
58  *                     Ideas
59  *
60  *               "Cort Dougan" <cort@cs.nmt.edu>
61  *                     CHRP fixes and PReP cleanup
62  *
63  *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
64  *                     G400 support
65  *
66  * (following author is not in any relation with this code, but his code
67  *  is included in this driver)
68  *
69  * Based on framebuffer driver for VBE 2.0 compliant graphic boards
70  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
71  *
72  * (following author is not in any relation with this code, but his ideas
73  *  were used when writting this driver)
74  *
75  *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
76  *
77  */
78 
79 #include "matroxfb_accel.h"
80 #include "matroxfb_DAC1064.h"
81 #include "matroxfb_Ti3026.h"
82 #include "matroxfb_misc.h"
83 
84 #define curr_ydstorg(x)	ACCESS_FBINFO2(x, curr.ydstorg.pixels)
85 
86 #define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
87 
matrox_cfbX_init(WPMINFO struct display * p)88 void matrox_cfbX_init(WPMINFO struct display* p) {
89 	u_int32_t maccess;
90 	u_int32_t mpitch;
91 	u_int32_t mopmode;
92 
93 	DBG("matrox_cfbX_init")
94 
95 	mpitch = p->var.xres_virtual;
96 
97 	if (p->type == FB_TYPE_TEXT) {
98 		maccess = 0x00000000;
99 		mpitch = (mpitch >> 4) | 0x8000; /* set something */
100 		mopmode = M_OPMODE_8BPP;
101 	} else {
102 		switch (p->var.bits_per_pixel) {
103 		case 4:		maccess = 0x00000000;	/* accelerate as 8bpp video */
104 				mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
105 				mopmode = M_OPMODE_4BPP;
106 				break;
107 		case 8:		maccess = 0x00000000;
108 				mopmode = M_OPMODE_8BPP;
109 				break;
110 		case 16:	if (p->var.green.length == 5)
111 					maccess = 0xC0000001;
112 				else
113 					maccess = 0x40000001;
114 				mopmode = M_OPMODE_16BPP;
115 				break;
116 		case 24:	maccess = 0x00000003;
117 				mopmode = M_OPMODE_24BPP;
118 				break;
119 		case 32:	maccess = 0x00000002;
120 				mopmode = M_OPMODE_32BPP;
121 				break;
122 		default:	maccess = 0x00000000;
123 				mopmode = 0x00000000;
124 				break;	/* turn off acceleration!!! */
125 		}
126 	}
127 	mga_fifo(8);
128 	mga_outl(M_PITCH, mpitch);
129 	mga_outl(M_YDSTORG, curr_ydstorg(MINFO));
130 	if (ACCESS_FBINFO(capable.plnwt))
131 		mga_outl(M_PLNWT, -1);
132 	if (ACCESS_FBINFO(capable.srcorg)) {
133 		mga_outl(M_SRCORG, 0);
134 		mga_outl(M_DSTORG, 0);
135 	}
136 	mga_outl(M_OPMODE, mopmode);
137 	mga_outl(M_CXBNDRY, 0xFFFF0000);
138 	mga_outl(M_YTOP, 0);
139 	mga_outl(M_YBOT, 0x01FFFFFF);
140 	mga_outl(M_MACCESS, maccess);
141 	ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
142 	if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC;
143 	ACCESS_FBINFO(accel.m_opmode) = mopmode;
144 }
145 
146 EXPORT_SYMBOL(matrox_cfbX_init);
147 
matrox_cfbX_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)148 static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx, int height, int width) {
149 	int pixx = p->var.xres_virtual, start, end;
150 	CRITFLAGS
151 	MINFO_FROM_DISP(p);
152 
153 	DBG("matrox_cfbX_bmove")
154 
155 	CRITBEGIN
156 
157 	sx *= fontwidth(p);
158 	dx *= fontwidth(p);
159 	width *= fontwidth(p);
160 	height *= fontheight(p);
161 	sy *= fontheight(p);
162 	dy *= fontheight(p);
163 	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
164 		mga_fifo(2);
165 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
166 			 M_DWG_BFCOL | M_DWG_REPLACE);
167 		mga_outl(M_AR5, pixx);
168 		width--;
169 		start = sy*pixx+sx+curr_ydstorg(MINFO);
170 		end = start+width;
171 	} else {
172 		mga_fifo(3);
173 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
174 		mga_outl(M_SGN, 5);
175 		mga_outl(M_AR5, -pixx);
176 		width--;
177 		end = (sy+height-1)*pixx+sx+curr_ydstorg(MINFO);
178 		start = end+width;
179 		dy += height-1;
180 	}
181 	mga_fifo(4);
182 	mga_outl(M_AR0, end);
183 	mga_outl(M_AR3, start);
184 	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
185 	mga_ydstlen(dy, height);
186 	WaitTillIdle();
187 
188 	CRITEND
189 }
190 
191 #ifdef FBCON_HAS_CFB4
matrox_cfb4_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)192 static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx, int height, int width) {
193 	int pixx, start, end;
194 	CRITFLAGS
195 	MINFO_FROM_DISP(p);
196 	/* both (sx or dx or width) and fontwidth() are odd, so their multiply is
197 	   also odd, that means that we cannot use acceleration */
198 
199 	DBG("matrox_cfb4_bmove")
200 
201 	CRITBEGIN
202 
203 	if ((sx | dx | width) & fontwidth(p) & 1) {
204 		fbcon_cfb4_bmove(p, sy, sx, dy, dx, height, width);
205 		return;
206 	}
207 	sx *= fontwidth(p);
208 	dx *= fontwidth(p);
209 	width *= fontwidth(p);
210 	height *= fontheight(p);
211 	sy *= fontheight(p);
212 	dy *= fontheight(p);
213 	pixx = p->var.xres_virtual >> 1;
214 	sx >>= 1;
215 	dx >>= 1;
216 	width >>= 1;
217 	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
218 		mga_fifo(2);
219 		mga_outl(M_AR5, pixx);
220 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
221 			M_DWG_BFCOL | M_DWG_REPLACE);
222 		width--;
223 		start = sy*pixx+sx+curr_ydstorg(MINFO);
224 		end = start+width;
225 	} else {
226 		mga_fifo(3);
227 		mga_outl(M_SGN, 5);
228 		mga_outl(M_AR5, -pixx);
229 		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
230 		width--;
231 		end = (sy+height-1)*pixx+sx+curr_ydstorg(MINFO);
232 		start = end+width;
233 		dy += height-1;
234 	}
235 	mga_fifo(5);
236 	mga_outl(M_AR0, end);
237 	mga_outl(M_AR3, start);
238 	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
239 	mga_outl(M_YDST, dy*pixx >> 5);
240 	mga_outl(M_LEN | M_EXEC, height);
241 	WaitTillIdle();
242 
243 	CRITEND
244 }
245 #endif
246 
matroxfb_accel_clear(WPMINFO u_int32_t color,int sy,int sx,int height,int width)247 static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int height,
248 		int width) {
249 	CRITFLAGS
250 
251 	DBG("matroxfb_accel_clear")
252 
253 	CRITBEGIN
254 
255 	mga_fifo(5);
256 	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE);
257 	mga_outl(M_FCOL, color);
258 	mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
259 	mga_ydstlen(sy, height);
260 	WaitTillIdle();
261 
262 	CRITEND
263 }
264 
matrox_cfbX_clear(u_int32_t color,struct display * p,int sy,int sx,int height,int width)265 static void matrox_cfbX_clear(u_int32_t color, struct display* p, int sy, int sx, int height, int width) {
266 
267 	DBG("matrox_cfbX_clear")
268 
269 	matroxfb_accel_clear(PMXINFO(p) color, sy * fontheight(p), sx * fontwidth(p),
270 			     height * fontheight(p), width * fontwidth(p));
271 }
272 
273 #ifdef FBCON_HAS_CFB4
matrox_cfb4_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)274 static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
275 	u_int32_t bgx;
276 	int whattodo;
277 	CRITFLAGS
278 	MINFO_FROM_DISP(p);
279 
280 	DBG("matrox_cfb4_clear")
281 
282 	CRITBEGIN
283 
284 	whattodo = 0;
285 	bgx = attr_bgcol_ec(p, conp);
286 	bgx |= bgx << 4;
287 	bgx |= bgx << 8;
288 	bgx |= bgx << 16;
289 	sy *= fontheight(p);
290 	sx *= fontwidth(p);
291 	height *= fontheight(p);
292 	width *= fontwidth(p);
293 	if (sx & 1) {
294 		sx ++;
295 		if (!width) return;
296 		width --;
297 		whattodo = 1;
298 	}
299 	if (width & 1) {
300 		whattodo |= 2;
301 	}
302 	width >>= 1;
303 	sx >>= 1;
304 	if (width) {
305 		mga_fifo(5);
306 		mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE2);
307 		mga_outl(M_FCOL, bgx);
308 		mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
309 		mga_outl(M_YDST, sy * p->var.xres_virtual >> 6);
310 		mga_outl(M_LEN | M_EXEC, height);
311 		WaitTillIdle();
312 	}
313 	if (whattodo) {
314 		u_int32_t step = p->var.xres_virtual >> 1;
315 		vaddr_t vbase = ACCESS_FBINFO(video.vbase);
316 		if (whattodo & 1) {
317 			unsigned int uaddr = sy * step + sx - 1;
318 			u_int32_t loop;
319 			u_int8_t bgx2 = bgx & 0xF0;
320 			for (loop = height; loop > 0; loop --) {
321 				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
322 				uaddr += step;
323 			}
324 		}
325 		if (whattodo & 2) {
326 			unsigned int uaddr = sy * step + sx + width;
327 			u_int32_t loop;
328 			u_int8_t bgx2 = bgx & 0x0F;
329 			for (loop = height; loop > 0; loop --) {
330 				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
331 				uaddr += step;
332 			}
333 		}
334 	}
335 
336 	CRITEND
337 }
338 #endif
339 
340 #ifdef FBCON_HAS_CFB8
matrox_cfb8_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)341 static void matrox_cfb8_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
342 	u_int32_t bgx;
343 
344 	DBG("matrox_cfb8_clear")
345 
346 	bgx = attr_bgcol_ec(p, conp);
347 	bgx |= bgx << 8;
348 	bgx |= bgx << 16;
349 	matrox_cfbX_clear(bgx, p, sy, sx, height, width);
350 }
351 #endif
352 
353 #ifdef FBCON_HAS_CFB16
matrox_cfb16_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)354 static void matrox_cfb16_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
355 	u_int32_t bgx;
356 
357 	DBG("matrox_cfb16_clear")
358 
359 	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
360 	matrox_cfbX_clear((bgx << 16) | bgx, p, sy, sx, height, width);
361 }
362 #endif
363 
364 #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
matrox_cfb32_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)365 static void matrox_cfb32_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
366 	u_int32_t bgx;
367 
368 	DBG("matrox_cfb32_clear")
369 
370 	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
371 	matrox_cfbX_clear(bgx, p, sy, sx, height, width);
372 }
373 #endif
374 
matrox_cfbX_fastputc(u_int32_t fgx,u_int32_t bgx,struct display * p,int c,int yy,int xx)375 static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
376 	unsigned int charcell;
377 	unsigned int ar3;
378 	CRITFLAGS
379 	MINFO_FROM_DISP(p);
380 
381 	charcell = fontwidth(p) * fontheight(p);
382 	yy *= fontheight(p);
383 	xx *= fontwidth(p);
384 
385 	CRITBEGIN
386 
387 	mga_fifo(8);
388 	mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
389 
390 	mga_outl(M_FCOL, fgx);
391 	mga_outl(M_BCOL, bgx);
392 	mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
393 	ar3 = ACCESS_FBINFO(fastfont.mgabase) + (c & p->charmask) * charcell;
394 	mga_outl(M_AR3, ar3);
395 	mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
396 	mga_ydstlen(yy, fontheight(p));
397 	WaitTillIdle();
398 
399 	CRITEND
400 }
401 
matrox_cfbX_putc(u_int32_t fgx,u_int32_t bgx,struct display * p,int c,int yy,int xx)402 static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
403 	u_int32_t ar0;
404 	u_int32_t step;
405 	CRITFLAGS
406 	MINFO_FROM_DISP(p);
407 
408 	DBG_HEAVY("matrox_cfbX_putc");
409 
410 	yy *= fontheight(p);
411 	xx *= fontwidth(p);
412 
413 	CRITBEGIN
414 
415 #ifdef __BIG_ENDIAN
416 	WaitTillIdle();
417 	mga_outl(M_OPMODE, M_OPMODE_8BPP);
418 #else
419 	mga_fifo(7);
420 #endif
421 	ar0 = fontwidth(p) - 1;
422 	mga_outl(M_FXBNDRY, ((xx+ar0)<<16) | xx);
423 	if (fontwidth(p) <= 8)
424 		step = 1;
425 	else if (fontwidth(p) <= 16)
426 		step = 2;
427 	else
428 		step = 4;
429 	if (fontwidth(p) == step << 3) {
430 		size_t charcell = fontheight(p)*step;
431 		/* TODO: Align charcell to 4B for BE */
432 		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
433 		mga_outl(M_FCOL, fgx);
434 		mga_outl(M_BCOL, bgx);
435 		mga_outl(M_AR3, 0);
436 		mga_outl(M_AR0, fontheight(p)*fontwidth(p)-1);
437 		mga_ydstlen(yy, fontheight(p));
438 		mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, p->fontdata+(c&p->charmask)*charcell, charcell);
439 	} else {
440 		u8* chardata = p->fontdata+(c&p->charmask)*fontheight(p)*step;
441 		int i;
442 
443 		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
444 		mga_outl(M_FCOL, fgx);
445 		mga_outl(M_BCOL, bgx);
446 		mga_outl(M_AR5, 0);
447 		mga_outl(M_AR3, 0);
448 		mga_outl(M_AR0, ar0);
449 		mga_ydstlen(yy, fontheight(p));
450 
451 		switch (step) {
452 		case 1:
453 			for (i = fontheight(p); i > 0; i--) {
454 #ifdef __LITTLE_ENDIAN
455 				mga_outl(0, *chardata++);
456 #else
457 				mga_outl(0, (*chardata++) << 24);
458 #endif
459 			}
460 			break;
461 		case 2:
462 			for (i = fontheight(p); i > 0; i--) {
463 #ifdef __LITTLE_ENDIAN
464 				mga_outl(0, *(u_int16_t*)chardata);
465 #else
466 				mga_outl(0, (*(u_int16_t*)chardata) << 16);
467 #endif
468 				chardata += 2;
469 			}
470 			break;
471 		case 4:
472 			mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, chardata, fontheight(p) * 4);
473 			break;
474 		}
475 	}
476 	WaitTillIdle();
477 #ifdef __BIG_ENDIAN
478 	mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
479 #endif
480 	CRITEND
481 }
482 
483 #ifdef FBCON_HAS_CFB8
matrox_cfb8_putc(struct vc_data * conp,struct display * p,int c,int yy,int xx)484 static void matrox_cfb8_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
485 	u_int32_t fgx, bgx;
486 	MINFO_FROM_DISP(p);
487 
488 	DBG_HEAVY("matroxfb_cfb8_putc");
489 
490 	fgx = attr_fgcol(p, c);
491 	bgx = attr_bgcol(p, c);
492 	fgx |= (fgx << 8);
493 	fgx |= (fgx << 16);
494 	bgx |= (bgx << 8);
495 	bgx |= (bgx << 16);
496 	ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
497 }
498 #endif
499 
500 #ifdef FBCON_HAS_CFB16
matrox_cfb16_putc(struct vc_data * conp,struct display * p,int c,int yy,int xx)501 static void matrox_cfb16_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
502 	u_int32_t fgx, bgx;
503 	MINFO_FROM_DISP(p);
504 
505 	DBG_HEAVY("matroxfb_cfb16_putc");
506 
507 	fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, c)];
508 	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, c)];
509 	fgx |= (fgx << 16);
510 	bgx |= (bgx << 16);
511 	ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
512 }
513 #endif
514 
515 #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
matrox_cfb32_putc(struct vc_data * conp,struct display * p,int c,int yy,int xx)516 static void matrox_cfb32_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
517 	u_int32_t fgx, bgx;
518 	MINFO_FROM_DISP(p);
519 
520 	DBG_HEAVY("matroxfb_cfb32_putc");
521 
522 	fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, c)];
523 	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, c)];
524 	ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
525 }
526 #endif
527 
matrox_cfbX_fastputcs(u_int32_t fgx,u_int32_t bgx,struct display * p,const unsigned short * s,int count,int yy,int xx)528 static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
529 	unsigned int charcell;
530 	CRITFLAGS
531 	MINFO_FROM_DISP(p);
532 
533 	yy *= fontheight(p);
534 	xx *= fontwidth(p);
535 	charcell = fontwidth(p) * fontheight(p);
536 
537 	CRITBEGIN
538 
539 	mga_fifo(3);
540 	mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
541 	mga_outl(M_FCOL, fgx);
542 	mga_outl(M_BCOL, bgx);
543 	while (count--) {
544 		u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (scr_readw(s++) & p->charmask)*charcell;
545 
546 		mga_fifo(4);
547 		mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
548 		mga_outl(M_AR3, ar3);
549 		mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
550 		mga_ydstlen(yy, fontheight(p));
551 		xx += fontwidth(p);
552 	}
553 	WaitTillIdle();
554 
555 	CRITEND
556 }
557 
matrox_cfbX_putcs(u_int32_t fgx,u_int32_t bgx,struct display * p,const unsigned short * s,int count,int yy,int xx)558 static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
559 	u_int32_t step;
560 	u_int32_t ydstlen;
561 	u_int32_t xlen;
562 	u_int32_t ar0;
563 	u_int32_t charcell;
564 	u_int32_t fxbndry;
565 	vaddr_t mmio;
566 	int easy;
567 	CRITFLAGS
568 	MINFO_FROM_DISP(p);
569 
570 	DBG_HEAVY("matroxfb_cfbX_putcs");
571 
572 	yy *= fontheight(p);
573 	xx *= fontwidth(p);
574 	if (fontwidth(p) <= 8)
575 		step = 1;
576 	else if (fontwidth(p) <= 16)
577 		step = 2;
578 	else
579 		step = 4;
580 	charcell = fontheight(p)*step;
581 	xlen = (charcell + 3) & ~3;
582 	ydstlen = (yy << 16) | fontheight(p);
583 	if (fontwidth(p) == step << 3) {
584 		ar0 = fontheight(p)*fontwidth(p) - 1;
585 		easy = 1;
586 	} else {
587 		ar0 = fontwidth(p) - 1;
588 		easy = 0;
589 	}
590 
591 	CRITBEGIN
592 
593 #ifdef __BIG_ENDIAN
594 	WaitTillIdle();
595 	mga_outl(M_OPMODE, M_OPMODE_8BPP);
596 #else
597 	mga_fifo(3);
598 #endif
599 	if (easy)
600 		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
601 	else
602 		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
603 	mga_outl(M_FCOL, fgx);
604 	mga_outl(M_BCOL, bgx);
605 	fxbndry = ((xx + fontwidth(p) - 1) << 16) | xx;
606 	mmio = ACCESS_FBINFO(mmio.vbase);
607 	while (count--) {
608 		u_int8_t* chardata = p->fontdata + (scr_readw(s++) & p->charmask)*charcell;
609 
610 		mga_fifo(6);
611 		mga_writel(mmio, M_FXBNDRY, fxbndry);
612 		mga_writel(mmio, M_AR0, ar0);
613 		mga_writel(mmio, M_AR3, 0);
614 		if (easy) {
615 			mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
616 			mga_memcpy_toio(mmio, 0, chardata, xlen);
617 		} else {
618 			mga_writel(mmio, M_AR5, 0);
619 			mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
620 			switch (step) {
621 				case 1:	{
622 						u_int8_t* charend = chardata + charcell;
623 						for (; chardata != charend; chardata++) {
624 #ifdef __LITTLE_ENDIAN
625 							mga_writel(mmio, 0, *chardata);
626 #else
627 							mga_writel(mmio, 0, (*chardata) << 24);
628 #endif
629 						}
630 					}
631 					break;
632 				case 2:	{
633 						u_int8_t* charend = chardata + charcell;
634 						for (; chardata != charend; chardata += 2) {
635 #ifdef __LITTLE_ENDIAN
636 							mga_writel(mmio, 0, *(u_int16_t*)chardata);
637 #else
638 							mga_writel(mmio, 0, (*(u_int16_t*)chardata) << 16);
639 #endif
640 						}
641 					}
642 					break;
643 				default:
644 					mga_memcpy_toio(mmio, 0, chardata, charcell);
645 					break;
646 			}
647 		}
648 		fxbndry += fontwidth(p) + (fontwidth(p) << 16);
649 	}
650 	WaitTillIdle();
651 #ifdef __BIG_ENDIAN
652 	mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
653 #endif
654 	CRITEND
655 }
656 
657 #ifdef FBCON_HAS_CFB8
matrox_cfb8_putcs(struct vc_data * conp,struct display * p,const unsigned short * s,int count,int yy,int xx)658 static void matrox_cfb8_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
659 	u_int16_t c;
660 	u_int32_t fgx, bgx;
661 	MINFO_FROM_DISP(p);
662 
663 	DBG_HEAVY("matroxfb_cfb8_putcs");
664 
665 	c = scr_readw(s);
666 	fgx = attr_fgcol(p, c);
667 	bgx = attr_bgcol(p, c);
668 	fgx |= (fgx << 8);
669 	fgx |= (fgx << 16);
670 	bgx |= (bgx << 8);
671 	bgx |= (bgx << 16);
672 	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
673 }
674 #endif
675 
676 #ifdef FBCON_HAS_CFB16
matrox_cfb16_putcs(struct vc_data * conp,struct display * p,const unsigned short * s,int count,int yy,int xx)677 static void matrox_cfb16_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
678 	u_int16_t c;
679 	u_int32_t fgx, bgx;
680 	MINFO_FROM_DISP(p);
681 
682 	DBG_HEAVY("matroxfb_cfb16_putcs");
683 
684 	c = scr_readw(s);
685 	fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, c)];
686 	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, c)];
687 	fgx |= (fgx << 16);
688 	bgx |= (bgx << 16);
689 	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
690 }
691 #endif
692 
693 #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
matrox_cfb32_putcs(struct vc_data * conp,struct display * p,const unsigned short * s,int count,int yy,int xx)694 static void matrox_cfb32_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
695 	u_int16_t c;
696 	u_int32_t fgx, bgx;
697 	MINFO_FROM_DISP(p);
698 
699 	DBG_HEAVY("matroxfb_cfb32_putcs");
700 
701 	c = scr_readw(s);
702 	fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, c)];
703 	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, c)];
704 	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
705 }
706 #endif
707 
708 #ifdef FBCON_HAS_CFB4
matrox_cfb4_revc(struct display * p,int xx,int yy)709 static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
710 	CRITFLAGS
711 	MINFO_FROM_DISP(p);
712 
713 	DBG_LOOP("matroxfb_cfb4_revc");
714 
715 	if (fontwidth(p) & 1) {
716 		fbcon_cfb4_revc(p, xx, yy);
717 		return;
718 	}
719 	yy *= fontheight(p);
720 	xx *= fontwidth(p);
721 	xx |= (xx + fontwidth(p)) << 16;
722 	xx >>= 1;
723 
724 	CRITBEGIN
725 
726 	mga_fifo(5);
727 	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
728 	mga_outl(M_FCOL, 0xFFFFFFFF);
729 	mga_outl(M_FXBNDRY, xx);
730 	mga_outl(M_YDST, yy * p->var.xres_virtual >> 6);
731 	mga_outl(M_LEN | M_EXEC, fontheight(p));
732 	WaitTillIdle();
733 
734 	CRITEND
735 }
736 #endif
737 
738 #ifdef FBCON_HAS_CFB8
matrox_cfb8_revc(struct display * p,int xx,int yy)739 static void matrox_cfb8_revc(struct display* p, int xx, int yy) {
740 	CRITFLAGS
741 	MINFO_FROM_DISP(p);
742 
743 	DBG_LOOP("matrox_cfb8_revc")
744 
745 	yy *= fontheight(p);
746 	xx *= fontwidth(p);
747 
748 	CRITBEGIN
749 
750 	mga_fifo(4);
751 	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
752 	mga_outl(M_FCOL, 0x0F0F0F0F);
753 	mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
754 	mga_ydstlen(yy, fontheight(p));
755 	WaitTillIdle();
756 
757 	CRITEND
758 }
759 #endif
760 
761 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
matrox_cfbX_revc(struct display * p,int xx,int yy)762 static void matrox_cfbX_revc(struct display* p, int xx, int yy) {
763 	CRITFLAGS
764 	MINFO_FROM_DISP(p);
765 
766 	DBG_LOOP("matrox_cfbX_revc")
767 
768 	yy *= fontheight(p);
769 	xx *= fontwidth(p);
770 
771 	CRITBEGIN
772 
773 	mga_fifo(4);
774 	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
775 	mga_outl(M_FCOL, 0xFFFFFFFF);
776 	mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
777 	mga_ydstlen(yy, fontheight(p));
778 	WaitTillIdle();
779 
780 	CRITEND
781 }
782 #endif
783 
matrox_cfbX_clear_margins(struct vc_data * conp,struct display * p,int bottom_only)784 static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) {
785 	unsigned int bottom_height, right_width;
786 	unsigned int bottom_start, right_start;
787 	unsigned int cell_h, cell_w;
788 
789 	DBG("matrox_cfbX_clear_margins")
790 
791 	cell_w = fontwidth(p);
792 	if (!cell_w) return;	/* PARANOID */
793 	right_width = p->var.xres % cell_w;
794 	right_start = p->var.xres - right_width;
795 	if (!bottom_only && right_width) {
796 		/* clear whole right margin, not only visible portion */
797 		matroxfb_accel_clear(     PMXINFO(p)
798 			     /* color */  0x00000000,
799 			     /* y */      0,
800 			     /* x */      p->var.xoffset + right_start,
801 			     /* height */ p->var.yres_virtual,
802 			     /* width */  right_width);
803 	}
804 	cell_h = fontheight(p);
805 	if (!cell_h) return;	/* PARANOID */
806 	bottom_height = p->var.yres % cell_h;
807 	if (bottom_height) {
808 		bottom_start = p->var.yres - bottom_height;
809 		matroxfb_accel_clear(		  PMXINFO(p)
810 				     /* color */  0x00000000,
811 				     /* y */	  p->var.yoffset + bottom_start,
812 				     /* x */	  p->var.xoffset,
813 				     /* height */ bottom_height,
814 				     /* width */  right_start);
815 	}
816 }
817 
matrox_text_setup(struct display * p)818 static void matrox_text_setup(struct display* p) {
819 	MINFO_FROM_DISP(p);
820 
821 	p->next_line = p->line_length ? p->line_length : ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
822 	p->next_plane = 0;
823 }
824 
matrox_text_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)825 static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
826 		int height, int width) {
827 	unsigned int srcoff;
828 	unsigned int dstoff;
829 	unsigned int step;
830 	CRITFLAGS
831 	MINFO_FROM_DISP(p);
832 
833 	CRITBEGIN
834 
835 	step = ACCESS_FBINFO(devflags.textstep);
836 	srcoff = (sy * p->next_line) + (sx * step);
837 	dstoff = (dy * p->next_line) + (dx * step);
838 	if (dstoff < srcoff) {
839 		while (height > 0) {
840 			int i;
841 			for (i = width; i > 0; dstoff += step, srcoff += step, i--)
842 				mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
843 			height--;
844 			dstoff += p->next_line - width * step;
845 			srcoff += p->next_line - width * step;
846 		}
847 	} else {
848 		unsigned int off;
849 
850 		off = (height - 1) * p->next_line + (width - 1) * step;
851 		srcoff += off;
852 		dstoff += off;
853 		while (height > 0) {
854 			int i;
855 			for (i = width; i > 0; dstoff -= step, srcoff -= step, i--)
856 				mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
857 			dstoff -= p->next_line - width * step;
858 			srcoff -= p->next_line - width * step;
859 			height--;
860 		}
861 	}
862 	CRITEND
863 }
864 
matrox_text_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)865 static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, int sx,
866 		int height, int width) {
867 	unsigned int offs;
868 	unsigned int val;
869 	unsigned int step;
870 	CRITFLAGS
871 	MINFO_FROM_DISP(p);
872 
873 	step = ACCESS_FBINFO(devflags.textstep);
874 	offs = sy * p->next_line + sx * step;
875 	val = ntohs((attr_bgcol(p, conp->vc_video_erase_char) << 4) | attr_fgcol(p, conp->vc_video_erase_char) | (' ' << 8));
876 
877 	CRITBEGIN
878 
879 	while (height > 0) {
880 		int i;
881 		for (i = width; i > 0; offs += step, i--)
882 			mga_writew(ACCESS_FBINFO(video.vbase), offs, val);
883 		offs += p->next_line - width * step;
884 		height--;
885 	}
886 	CRITEND
887 }
888 
matrox_text_putc(struct vc_data * conp,struct display * p,int c,int yy,int xx)889 static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
890 	unsigned int offs;
891 	unsigned int chr;
892 	unsigned int step;
893 	CRITFLAGS
894 	MINFO_FROM_DISP(p);
895 
896 	step = ACCESS_FBINFO(devflags.textstep);
897 	offs = yy * p->next_line + xx * step;
898 	chr = attr_fgcol(p,c) | (attr_bgcol(p,c) << 4) | ((c & p->charmask) << 8);
899 	if (chr & 0x10000) chr |= 0x08;
900 
901 	CRITBEGIN
902 
903 	mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(chr));
904 
905 	CRITEND
906 }
907 
matrox_text_putcs(struct vc_data * conp,struct display * p,const unsigned short * s,int count,int yy,int xx)908 static void matrox_text_putcs(struct vc_data* conp, struct display* p, const unsigned short* s,
909 		int count, int yy, int xx) {
910 	unsigned int offs;
911 	unsigned int attr;
912 	unsigned int step;
913 	u_int16_t c;
914 	CRITFLAGS
915 	MINFO_FROM_DISP(p);
916 
917 	step = ACCESS_FBINFO(devflags.textstep);
918 	offs = yy * p->next_line + xx * step;
919 	c = scr_readw(s);
920 	attr = attr_fgcol(p, c) | (attr_bgcol(p, c) << 4);
921 
922 	CRITBEGIN
923 
924 	while (count-- > 0) {
925 		unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
926 		if (chr & 0x10000) chr ^= 0x10008;
927 		mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
928 		offs += step;
929 	}
930 
931 	CRITEND
932 }
933 
matrox_text_revc(struct display * p,int xx,int yy)934 static void matrox_text_revc(struct display* p, int xx, int yy) {
935 	unsigned int offs;
936 	unsigned int step;
937 	CRITFLAGS
938 	MINFO_FROM_DISP(p);
939 
940 	step = ACCESS_FBINFO(devflags.textstep);
941 	offs = yy * p->next_line + xx * step + 1;
942 
943 	CRITBEGIN
944 
945 	mga_writeb(ACCESS_FBINFO(video.vbase), offs, mga_readb(ACCESS_FBINFO(video.vbase), offs) ^ 0x77);
946 
947 	CRITEND
948 }
949 
matrox_text_createcursor(WPMINFO struct display * p)950 static void matrox_text_createcursor(WPMINFO struct display* p) {
951 	CRITFLAGS
952 
953 	if (ACCESS_FBINFO(currcon_display) != p)
954 		return;
955 
956 	matroxfb_createcursorshape(PMINFO p, 0);
957 
958 	CRITBEGIN
959 
960 	mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
961 	mga_setr(M_CRTC_INDEX, 0x0B, ACCESS_FBINFO(cursor.d) - 1);
962 
963 	CRITEND
964 }
965 
matrox_text_cursor(struct display * p,int mode,int x,int y)966 static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
967 	unsigned int pos;
968 	CRITFLAGS
969 	MINFO_FROM_DISP(p);
970 
971 	if (ACCESS_FBINFO(currcon_display) != p)
972 		return;
973 
974 	if (mode == CM_ERASE) {
975 		if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
976 
977 			CRITBEGIN
978 
979 			mga_setr(M_CRTC_INDEX, 0x0A, 0x20);
980 
981 			CRITEND
982 
983 			ACCESS_FBINFO(cursor.state) = CM_ERASE;
984 		}
985 		return;
986 	}
987 	if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
988 		matrox_text_createcursor(PMINFO p);
989 
990 	/* DO NOT CHECK cursor.x != x because of matroxfb_vgaHWinit moves cursor to 0,0 */
991 	ACCESS_FBINFO(cursor.x) = x;
992 	ACCESS_FBINFO(cursor.y) = y;
993 	pos = p->next_line / ACCESS_FBINFO(devflags.textstep) * y + x;
994 
995 	CRITBEGIN
996 
997 	mga_setr(M_CRTC_INDEX, 0x0F, pos);
998 	mga_setr(M_CRTC_INDEX, 0x0E, pos >> 8);
999 
1000 	mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
1001 
1002 	CRITEND
1003 
1004 	ACCESS_FBINFO(cursor.state) = CM_DRAW;
1005 }
1006 
matrox_text_round(CPMINFO struct fb_var_screeninfo * var,struct display * p)1007 void matrox_text_round(CPMINFO struct fb_var_screeninfo* var, struct display* p) {
1008 	unsigned hf;
1009 	unsigned vf;
1010 	unsigned vxres;
1011 	unsigned ych;
1012 
1013 	hf = fontwidth(p);
1014 	if (!hf) hf = 8;
1015 	/* do not touch xres */
1016 	vxres = (var->xres_virtual + hf - 1) / hf;
1017 	if (vxres >= 256)
1018 		vxres = 255;
1019 	if (vxres < 16)
1020 		vxres = 16;
1021 	vxres = (vxres + 1) & ~1;	/* must be even */
1022 	vf = fontheight(p);
1023 	if (!vf) vf = 16;
1024 	if (var->yres < var->yres_virtual) {
1025 		ych = ACCESS_FBINFO(devflags.textvram) / vxres;
1026 		var->yres_virtual = ych * vf;
1027 	} else
1028 		ych = var->yres_virtual / vf;
1029 	if (vxres * ych > ACCESS_FBINFO(devflags.textvram)) {
1030 		ych = ACCESS_FBINFO(devflags.textvram) / vxres;
1031 		var->yres_virtual = ych * vf;
1032 	}
1033 	var->xres_virtual = vxres * hf;
1034 }
1035 
1036 EXPORT_SYMBOL(matrox_text_round);
1037 
matrox_text_setfont(struct display * p,int width,int height)1038 static int matrox_text_setfont(struct display* p, int width, int height) {
1039 	DBG("matrox_text_setfont");
1040 
1041 	if (p) {
1042 		MINFO_FROM_DISP(p);
1043 
1044 		matrox_text_round(PMINFO &p->var, p);
1045 		p->next_line = p->line_length = ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
1046 
1047 		if (p->conp)
1048 			matrox_text_createcursor(PMINFO p);
1049 	}
1050 	return 0;
1051 }
1052 
1053 #define matrox_cfb16_revc matrox_cfbX_revc
1054 #define matrox_cfb24_revc matrox_cfbX_revc
1055 #define matrox_cfb32_revc matrox_cfbX_revc
1056 
1057 #define matrox_cfb24_clear matrox_cfb32_clear
1058 #define matrox_cfb24_putc matrox_cfb32_putc
1059 #define matrox_cfb24_putcs matrox_cfb32_putcs
1060 
1061 #ifdef FBCON_HAS_VGATEXT
1062 static struct display_switch matroxfb_text = {
1063 	setup:		matrox_text_setup,
1064 	bmove:		matrox_text_bmove,
1065 	clear:		matrox_text_clear,
1066 	putc:		matrox_text_putc,
1067 	putcs:		matrox_text_putcs,
1068 	revc:		matrox_text_revc,
1069 	cursor:		matrox_text_cursor,
1070 	set_font:	matrox_text_setfont,
1071 	fontwidthmask:	FONTWIDTH(8)|FONTWIDTH(9)
1072 };
1073 #endif
1074 
1075 #ifdef FBCON_HAS_CFB4
1076 static struct display_switch matroxfb_cfb4 = {
1077 	setup:		fbcon_cfb4_setup,
1078 	bmove:		matrox_cfb4_bmove,
1079 	clear:		matrox_cfb4_clear,
1080 	putc:		fbcon_cfb4_putc,
1081 	putcs:		fbcon_cfb4_putcs,
1082 	revc:		matrox_cfb4_revc,
1083 	fontwidthmask:	FONTWIDTH(8) /* fix, fix, fix it */
1084 };
1085 #endif
1086 
1087 #ifdef FBCON_HAS_CFB8
1088 static struct display_switch matroxfb_cfb8 = {
1089 	setup:		fbcon_cfb8_setup,
1090 	bmove:		matrox_cfbX_bmove,
1091 	clear:		matrox_cfb8_clear,
1092 	putc:		matrox_cfb8_putc,
1093 	putcs:		matrox_cfb8_putcs,
1094 	revc:		matrox_cfb8_revc,
1095 	clear_margins:	matrox_cfbX_clear_margins,
1096 	fontwidthmask:	~1 /* FONTWIDTHS */
1097 };
1098 #endif
1099 
1100 #ifdef FBCON_HAS_CFB16
1101 static struct display_switch matroxfb_cfb16 = {
1102 	setup:		fbcon_cfb16_setup,
1103 	bmove:		matrox_cfbX_bmove,
1104 	clear:		matrox_cfb16_clear,
1105 	putc:		matrox_cfb16_putc,
1106 	putcs:		matrox_cfb16_putcs,
1107 	revc:		matrox_cfb16_revc,
1108 	clear_margins:	matrox_cfbX_clear_margins,
1109 	fontwidthmask:	~1 /* FONTWIDTHS */
1110 };
1111 #endif
1112 
1113 #ifdef FBCON_HAS_CFB24
1114 static struct display_switch matroxfb_cfb24 = {
1115 	setup:		fbcon_cfb24_setup,
1116 	bmove:		matrox_cfbX_bmove,
1117 	clear:		matrox_cfb24_clear,
1118 	putc:		matrox_cfb24_putc,
1119 	putcs:		matrox_cfb24_putcs,
1120 	revc:		matrox_cfb24_revc,
1121 	clear_margins:	matrox_cfbX_clear_margins,
1122 	fontwidthmask:	~1 /* FONTWIDTHS */ /* TODO: and what about non-aligned access on BE? I think that there are no in my code */
1123 };
1124 #endif
1125 
1126 #ifdef FBCON_HAS_CFB32
1127 static struct display_switch matroxfb_cfb32 = {
1128 	setup:		fbcon_cfb32_setup,
1129 	bmove:		matrox_cfbX_bmove,
1130 	clear:		matrox_cfb32_clear,
1131 	putc:		matrox_cfb32_putc,
1132 	putcs:		matrox_cfb32_putcs,
1133 	revc:		matrox_cfb32_revc,
1134 	clear_margins:	matrox_cfbX_clear_margins,
1135 	fontwidthmask:	~1 /* FONTWIDTHS */
1136 };
1137 #endif
1138 
initMatrox(WPMINFO struct display * p)1139 void initMatrox(WPMINFO struct display* p) {
1140 	struct display_switch *swtmp;
1141 
1142 	DBG("initMatrox")
1143 
1144 	if (ACCESS_FBINFO(currcon_display) != p)
1145 		return;
1146 	if (p->dispsw && p->conp)
1147 		fb_con.con_cursor(p->conp, CM_ERASE);
1148 	p->dispsw_data = NULL;
1149 	if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
1150 		if (p->type == FB_TYPE_TEXT) {
1151 			swtmp = &matroxfb_text;
1152 		} else {
1153 			switch (p->var.bits_per_pixel) {
1154 #ifdef FBCON_HAS_CFB4
1155 			case 4:
1156 				swtmp = &fbcon_cfb4;
1157 				break;
1158 #endif
1159 #ifdef FBCON_HAS_CFB8
1160 			case 8:
1161 				swtmp = &fbcon_cfb8;
1162 				break;
1163 #endif
1164 #ifdef FBCON_HAS_CFB16
1165 			case 16:
1166 				p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
1167 				swtmp = &fbcon_cfb16;
1168 				break;
1169 #endif
1170 #ifdef FBCON_HAS_CFB24
1171 			case 24:
1172 				p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
1173 				swtmp = &fbcon_cfb24;
1174 				break;
1175 #endif
1176 #ifdef FBCON_HAS_CFB32
1177 			case 32:
1178 				p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
1179 				swtmp = &fbcon_cfb32;
1180 				break;
1181 #endif
1182 			default:
1183 				p->dispsw = &fbcon_dummy;
1184 				return;
1185 			}
1186 		}
1187 		dprintk(KERN_INFO "matroxfb: acceleration disabled\n");
1188 	} else if (p->type == FB_TYPE_TEXT) {
1189 		swtmp = &matroxfb_text;
1190 	} else {
1191 		switch (p->var.bits_per_pixel) {
1192 #ifdef FBCON_HAS_CFB4
1193 		case 4:
1194 			swtmp = &matroxfb_cfb4;
1195 			break;
1196 #endif
1197 #ifdef FBCON_HAS_CFB8
1198 		case 8:
1199 			swtmp = &matroxfb_cfb8;
1200 			break;
1201 #endif
1202 #ifdef FBCON_HAS_CFB16
1203 		case 16:
1204 			p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
1205 			swtmp = &matroxfb_cfb16;
1206 			break;
1207 #endif
1208 #ifdef FBCON_HAS_CFB24
1209 		case 24:
1210 			p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
1211 			swtmp = &matroxfb_cfb24;
1212 			break;
1213 #endif
1214 #ifdef FBCON_HAS_CFB32
1215 		case 32:
1216 			p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
1217 			swtmp = &matroxfb_cfb32;
1218 			break;
1219 #endif
1220 		default:
1221 			p->dispsw = &fbcon_dummy;
1222 			return;
1223 		}
1224 	}
1225 	memcpy(&ACCESS_FBINFO(dispsw), swtmp, sizeof(ACCESS_FBINFO(dispsw)));
1226 	p->dispsw = &ACCESS_FBINFO(dispsw);
1227 	if ((p->type != FB_TYPE_TEXT) && ACCESS_FBINFO(devflags.hwcursor)) {
1228 		ACCESS_FBINFO(hw_switch)->selhwcursor(PMINFO p);
1229 	}
1230 }
1231 
1232 EXPORT_SYMBOL(initMatrox);
1233 
matrox_init_putc(WPMINFO struct display * p,void (* dac_createcursor)(WPMINFO struct display * p))1234 void matrox_init_putc(WPMINFO struct display* p, void (*dac_createcursor)(WPMINFO struct display* p)) {
1235 	int i;
1236 
1237 	if (p && p->conp) {
1238 		if (p->type == FB_TYPE_TEXT) {
1239 			matrox_text_createcursor(PMINFO p);
1240 			matrox_text_loadfont(PMINFO p);
1241 			i = 0;
1242 		} else {
1243 			dac_createcursor(PMINFO p);
1244 			i = matroxfb_fastfont_tryset(PMINFO p);
1245 		}
1246 	} else
1247 		i = 0;
1248 	if (i) {
1249 		ACCESS_FBINFO(curr.putc) = matrox_cfbX_fastputc;
1250 		ACCESS_FBINFO(curr.putcs) = matrox_cfbX_fastputcs;
1251 	} else {
1252 		ACCESS_FBINFO(curr.putc) = matrox_cfbX_putc;
1253 		ACCESS_FBINFO(curr.putcs) = matrox_cfbX_putcs;
1254 	}
1255 }
1256 
1257 EXPORT_SYMBOL(matrox_init_putc);
1258 
1259 MODULE_LICENSE("GPL");
1260