File: /usr/src/linux/drivers/video/matrox/matroxfb_accel.c

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     
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     static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx, int height, int width) {
147     	int pixx = p->var.xres_virtual, start, end;
148     	CRITFLAGS
149     	MINFO_FROM_DISP(p);
150     
151     	DBG("matrox_cfbX_bmove")
152     
153     	CRITBEGIN
154     
155     	sx *= fontwidth(p);
156     	dx *= fontwidth(p);
157     	width *= fontwidth(p);
158     	height *= fontheight(p);
159     	sy *= fontheight(p);
160     	dy *= fontheight(p);
161     	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
162     		mga_fifo(2);
163     		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
164     			 M_DWG_BFCOL | M_DWG_REPLACE);
165     		mga_outl(M_AR5, pixx);
166     		width--;
167     		start = sy*pixx+sx+curr_ydstorg(MINFO);
168     		end = start+width;
169     	} else {
170     		mga_fifo(3);
171     		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
172     		mga_outl(M_SGN, 5);
173     		mga_outl(M_AR5, -pixx);
174     		width--;
175     		end = (sy+height-1)*pixx+sx+curr_ydstorg(MINFO);
176     		start = end+width;
177     		dy += height-1;
178     	}
179     	mga_fifo(4);
180     	mga_outl(M_AR0, end);
181     	mga_outl(M_AR3, start);
182     	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
183     	mga_ydstlen(dy, height);
184     	WaitTillIdle();
185     
186     	CRITEND
187     }
188     
189     #ifdef FBCON_HAS_CFB4
190     static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx, int height, int width) {
191     	int pixx, start, end;
192     	CRITFLAGS
193     	MINFO_FROM_DISP(p);
194     	/* both (sx or dx or width) and fontwidth() are odd, so their multiply is
195     	   also odd, that means that we cannot use acceleration */
196     
197     	DBG("matrox_cfb4_bmove")
198     
199     	CRITBEGIN
200     
201     	if ((sx | dx | width) & fontwidth(p) & 1) {
202     		fbcon_cfb4_bmove(p, sy, sx, dy, dx, height, width);
203     		return;
204     	}
205     	sx *= fontwidth(p);
206     	dx *= fontwidth(p);
207     	width *= fontwidth(p);
208     	height *= fontheight(p);
209     	sy *= fontheight(p);
210     	dy *= fontheight(p);
211     	pixx = p->var.xres_virtual >> 1;
212     	sx >>= 1;
213     	dx >>= 1;
214     	width >>= 1;
215     	if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
216     		mga_fifo(2);
217     		mga_outl(M_AR5, pixx);
218     		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
219     			M_DWG_BFCOL | M_DWG_REPLACE);
220     		width--;
221     		start = sy*pixx+sx+curr_ydstorg(MINFO);
222     		end = start+width;
223     	} else {
224     		mga_fifo(3);
225     		mga_outl(M_SGN, 5);
226     		mga_outl(M_AR5, -pixx);
227     		mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
228     		width--;
229     		end = (sy+height-1)*pixx+sx+curr_ydstorg(MINFO);
230     		start = end+width;
231     		dy += height-1;
232     	}
233     	mga_fifo(5);
234     	mga_outl(M_AR0, end);
235     	mga_outl(M_AR3, start);
236     	mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
237     	mga_outl(M_YDST, dy*pixx >> 5);
238     	mga_outl(M_LEN | M_EXEC, height);
239     	WaitTillIdle();
240     
241     	CRITEND
242     }
243     #endif
244     
245     static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int height,
246     		int width) {
247     	CRITFLAGS
248     
249     	DBG("matroxfb_accel_clear")
250     
251     	CRITBEGIN
252     
253     	mga_fifo(5);
254     	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE);
255     	mga_outl(M_FCOL, color);
256     	mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
257     	mga_ydstlen(sy, height);
258     	WaitTillIdle();
259     
260     	CRITEND
261     }
262     
263     static void matrox_cfbX_clear(u_int32_t color, struct display* p, int sy, int sx, int height, int width) {
264     
265     	DBG("matrox_cfbX_clear")
266     
267     	matroxfb_accel_clear(PMXINFO(p) color, sy * fontheight(p), sx * fontwidth(p),
268     			     height * fontheight(p), width * fontwidth(p));
269     }
270     
271     #ifdef FBCON_HAS_CFB4
272     static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
273     	u_int32_t bgx;
274     	int whattodo;
275     	CRITFLAGS
276     	MINFO_FROM_DISP(p);
277     
278     	DBG("matrox_cfb4_clear")
279     
280     	CRITBEGIN
281     
282     	whattodo = 0;
283     	bgx = attr_bgcol_ec(p, conp);
284     	bgx |= bgx << 4;
285     	bgx |= bgx << 8;
286     	bgx |= bgx << 16;
287     	sy *= fontheight(p);
288     	sx *= fontwidth(p);
289     	height *= fontheight(p);
290     	width *= fontwidth(p);
291     	if (sx & 1) {
292     		sx ++;
293     		if (!width) return;
294     		width --;
295     		whattodo = 1;
296     	}
297     	if (width & 1) {
298     		whattodo |= 2;
299     	}
300     	width >>= 1;
301     	sx >>= 1;
302     	if (width) {
303     		mga_fifo(5);
304     		mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE2);
305     		mga_outl(M_FCOL, bgx);
306     		mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
307     		mga_outl(M_YDST, sy * p->var.xres_virtual >> 6);
308     		mga_outl(M_LEN | M_EXEC, height);
309     		WaitTillIdle();
310     	}
311     	if (whattodo) {
312     		u_int32_t step = p->var.xres_virtual >> 1;
313     		vaddr_t vbase = ACCESS_FBINFO(video.vbase);
314     		if (whattodo & 1) {
315     			unsigned int uaddr = sy * step + sx - 1;
316     			u_int32_t loop;
317     			u_int8_t bgx2 = bgx & 0xF0;
318     			for (loop = height; loop > 0; loop --) {
319     				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
320     				uaddr += step;
321     			}
322     		}
323     		if (whattodo & 2) {
324     			unsigned int uaddr = sy * step + sx + width;
325     			u_int32_t loop;
326     			u_int8_t bgx2 = bgx & 0x0F;
327     			for (loop = height; loop > 0; loop --) {
328     				mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
329     				uaddr += step;
330     			}
331     		}
332     	}
333     
334     	CRITEND
335     }
336     #endif
337     
338     #ifdef FBCON_HAS_CFB8
339     static void matrox_cfb8_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
340     	u_int32_t bgx;
341     
342     	DBG("matrox_cfb8_clear")
343     
344     	bgx = attr_bgcol_ec(p, conp);
345     	bgx |= bgx << 8;
346     	bgx |= bgx << 16;
347     	matrox_cfbX_clear(bgx, p, sy, sx, height, width);
348     }
349     #endif
350     
351     #ifdef FBCON_HAS_CFB16
352     static void matrox_cfb16_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
353     	u_int32_t bgx;
354     
355     	DBG("matrox_cfb16_clear")
356     
357     	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
358     	matrox_cfbX_clear((bgx << 16) | bgx, p, sy, sx, height, width);
359     }
360     #endif
361     
362     #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
363     static void matrox_cfb32_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
364     	u_int32_t bgx;
365     
366     	DBG("matrox_cfb32_clear")
367     
368     	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
369     	matrox_cfbX_clear(bgx, p, sy, sx, height, width);
370     }
371     #endif
372     
373     static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
374     	unsigned int charcell;
375     	unsigned int ar3;
376     	CRITFLAGS
377     	MINFO_FROM_DISP(p);
378     
379     	charcell = fontwidth(p) * fontheight(p);
380     	yy *= fontheight(p);
381     	xx *= fontwidth(p);
382     
383     	CRITBEGIN
384     
385     	mga_fifo(8);
386     	mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
387     
388     	mga_outl(M_FCOL, fgx);
389     	mga_outl(M_BCOL, bgx);
390     	mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
391     	ar3 = ACCESS_FBINFO(fastfont.mgabase) + (c & p->charmask) * charcell;
392     	mga_outl(M_AR3, ar3);
393     	mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
394     	mga_ydstlen(yy, fontheight(p));
395     	WaitTillIdle();
396     
397     	CRITEND
398     }
399     
400     static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
401     	u_int32_t ar0;
402     	u_int32_t step;
403     	CRITFLAGS
404     	MINFO_FROM_DISP(p);
405     
406     	DBG_HEAVY("matrox_cfbX_putc");
407     
408     	yy *= fontheight(p);
409     	xx *= fontwidth(p);
410     
411     	CRITBEGIN
412     
413     #ifdef __BIG_ENDIAN
414     	WaitTillIdle();
415     	mga_outl(M_OPMODE, M_OPMODE_8BPP);
416     #else
417     	mga_fifo(7);
418     #endif
419     	ar0 = fontwidth(p) - 1;
420     	mga_outl(M_FXBNDRY, ((xx+ar0)<<16) | xx);
421     	if (fontwidth(p) <= 8)
422     		step = 1;
423     	else if (fontwidth(p) <= 16)
424     		step = 2;
425     	else
426     		step = 4;
427     	if (fontwidth(p) == step << 3) {
428     		size_t charcell = fontheight(p)*step;
429     		/* TODO: Align charcell to 4B for BE */
430     		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
431     		mga_outl(M_FCOL, fgx);
432     		mga_outl(M_BCOL, bgx);
433     		mga_outl(M_AR3, 0);
434     		mga_outl(M_AR0, fontheight(p)*fontwidth(p)-1);
435     		mga_ydstlen(yy, fontheight(p));
436     		mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, p->fontdata+(c&p->charmask)*charcell, charcell);
437     	} else {
438     		u8* chardata = p->fontdata+(c&p->charmask)*fontheight(p)*step;
439     		int i;
440     
441     		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
442     		mga_outl(M_FCOL, fgx);
443     		mga_outl(M_BCOL, bgx);
444     		mga_outl(M_AR5, 0);
445     		mga_outl(M_AR3, 0);
446     		mga_outl(M_AR0, ar0);
447     		mga_ydstlen(yy, fontheight(p));
448     
449     		switch (step) {
450     		case 1:
451     			for (i = fontheight(p); i > 0; i--) {
452     #ifdef __LITTLE_ENDIAN
453     				mga_outl(0, *chardata++);
454     #else
455     				mga_outl(0, (*chardata++) << 24);
456     #endif
457     			}
458     			break;
459     		case 2:
460     			for (i = fontheight(p); i > 0; i--) {
461     #ifdef __LITTLE_ENDIAN
462     				mga_outl(0, *(u_int16_t*)chardata);
463     #else
464     				mga_outl(0, (*(u_int16_t*)chardata) << 16);
465     #endif
466     				chardata += 2;
467     			}
468     			break;
469     		case 4:
470     			mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, chardata, fontheight(p) * 4);
471     			break;
472     		}
473     	}
474     	WaitTillIdle();
475     #ifdef __BIG_ENDIAN
476     	mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
477     #endif
478     	CRITEND
479     }
480     
481     #ifdef FBCON_HAS_CFB8
482     static void matrox_cfb8_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
483     	u_int32_t fgx, bgx;
484     	MINFO_FROM_DISP(p);
485     
486     	DBG_HEAVY("matroxfb_cfb8_putc");
487     
488     	fgx = attr_fgcol(p, c);
489     	bgx = attr_bgcol(p, c);
490     	fgx |= (fgx << 8);
491     	fgx |= (fgx << 16);
492     	bgx |= (bgx << 8);
493     	bgx |= (bgx << 16);
494     	ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
495     }
496     #endif
497     
498     #ifdef FBCON_HAS_CFB16
499     static void matrox_cfb16_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
500     	u_int32_t fgx, bgx;
501     	MINFO_FROM_DISP(p);
502     
503     	DBG_HEAVY("matroxfb_cfb16_putc");
504     
505     	fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, c)];
506     	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, c)];
507     	fgx |= (fgx << 16);
508     	bgx |= (bgx << 16);
509     	ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
510     }
511     #endif
512     
513     #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
514     static void matrox_cfb32_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
515     	u_int32_t fgx, bgx;
516     	MINFO_FROM_DISP(p);
517     
518     	DBG_HEAVY("matroxfb_cfb32_putc");
519     
520     	fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, c)];
521     	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, c)];
522     	ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
523     }
524     #endif
525     
526     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) {
527     	unsigned int charcell;
528     	CRITFLAGS
529     	MINFO_FROM_DISP(p);
530     
531     	yy *= fontheight(p);
532     	xx *= fontwidth(p);
533     	charcell = fontwidth(p) * fontheight(p);
534     
535     	CRITBEGIN
536     
537     	mga_fifo(3);
538     	mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
539     	mga_outl(M_FCOL, fgx);
540     	mga_outl(M_BCOL, bgx);
541     	while (count--) {
542     		u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (scr_readw(s++) & p->charmask)*charcell;
543     
544     		mga_fifo(4);
545     		mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
546     		mga_outl(M_AR3, ar3);
547     		mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
548     		mga_ydstlen(yy, fontheight(p));
549     		xx += fontwidth(p);
550     	}
551     	WaitTillIdle();
552     
553     	CRITEND
554     }
555     
556     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) {
557     	u_int32_t step;
558     	u_int32_t ydstlen;
559     	u_int32_t xlen;
560     	u_int32_t ar0;
561     	u_int32_t charcell;
562     	u_int32_t fxbndry;
563     	vaddr_t mmio;
564     	int easy;
565     	CRITFLAGS
566     	MINFO_FROM_DISP(p);
567     
568     	DBG_HEAVY("matroxfb_cfbX_putcs");
569     
570     	yy *= fontheight(p);
571     	xx *= fontwidth(p);
572     	if (fontwidth(p) <= 8)
573     		step = 1;
574     	else if (fontwidth(p) <= 16)
575     		step = 2;
576     	else
577     		step = 4;
578     	charcell = fontheight(p)*step;
579     	xlen = (charcell + 3) & ~3;
580     	ydstlen = (yy << 16) | fontheight(p);
581     	if (fontwidth(p) == step << 3) {
582     		ar0 = fontheight(p)*fontwidth(p) - 1;
583     		easy = 1;
584     	} else {
585     		ar0 = fontwidth(p) - 1;
586     		easy = 0;
587     	}
588     
589     	CRITBEGIN
590     
591     #ifdef __BIG_ENDIAN
592     	WaitTillIdle();
593     	mga_outl(M_OPMODE, M_OPMODE_8BPP);
594     #else
595     	mga_fifo(3);
596     #endif
597     	if (easy)
598     		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
599     	else
600     		mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
601     	mga_outl(M_FCOL, fgx);
602     	mga_outl(M_BCOL, bgx);
603     	fxbndry = ((xx + fontwidth(p) - 1) << 16) | xx;
604     	mmio = ACCESS_FBINFO(mmio.vbase);
605     	while (count--) {
606     		u_int8_t* chardata = p->fontdata + (scr_readw(s++) & p->charmask)*charcell;
607     
608     		mga_fifo(6);
609     		mga_writel(mmio, M_FXBNDRY, fxbndry);
610     		mga_writel(mmio, M_AR0, ar0);
611     		mga_writel(mmio, M_AR3, 0);
612     		if (easy) {
613     			mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
614     			mga_memcpy_toio(mmio, 0, chardata, xlen);
615     		} else {
616     			mga_writel(mmio, M_AR5, 0);
617     			mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
618     			switch (step) {
619     				case 1:	{
620     						u_int8_t* charend = chardata + charcell;
621     						for (; chardata != charend; chardata++) {
622     #ifdef __LITTLE_ENDIAN
623     							mga_writel(mmio, 0, *chardata);
624     #else
625     							mga_writel(mmio, 0, (*chardata) << 24);
626     #endif
627     						}
628     					}
629     					break;
630     				case 2:	{
631     						u_int8_t* charend = chardata + charcell;
632     						for (; chardata != charend; chardata += 2) {
633     #ifdef __LITTLE_ENDIAN
634     							mga_writel(mmio, 0, *(u_int16_t*)chardata);
635     #else
636     							mga_writel(mmio, 0, (*(u_int16_t*)chardata) << 16);
637     #endif
638     						}
639     					}
640     					break;
641     				default:
642     					mga_memcpy_toio(mmio, 0, chardata, charcell);
643     					break;
644     			}
645     		}
646     		fxbndry += fontwidth(p) + (fontwidth(p) << 16);
647     	}
648     	WaitTillIdle();
649     #ifdef __BIG_ENDIAN
650     	mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
651     #endif
652     	CRITEND
653     }
654     
655     #ifdef FBCON_HAS_CFB8
656     static void matrox_cfb8_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
657     	u_int32_t fgx, bgx;
658     	MINFO_FROM_DISP(p);
659     
660     	DBG_HEAVY("matroxfb_cfb8_putcs");
661     
662     	fgx = attr_fgcol(p, scr_readw(s));
663     	bgx = attr_bgcol(p, scr_readw(s));
664     	fgx |= (fgx << 8);
665     	fgx |= (fgx << 16);
666     	bgx |= (bgx << 8);
667     	bgx |= (bgx << 16);
668     	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
669     }
670     #endif
671     
672     #ifdef FBCON_HAS_CFB16
673     static void matrox_cfb16_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
674     	u_int32_t fgx, bgx;
675     	MINFO_FROM_DISP(p);
676     
677     	DBG_HEAVY("matroxfb_cfb16_putcs");
678     
679     	fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
680     	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
681     	fgx |= (fgx << 16);
682     	bgx |= (bgx << 16);
683     	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
684     }
685     #endif
686     
687     #if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
688     static void matrox_cfb32_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
689     	u_int32_t fgx, bgx;
690     	MINFO_FROM_DISP(p);
691     
692     	DBG_HEAVY("matroxfb_cfb32_putcs");
693     
694     	fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
695     	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
696     	ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
697     }
698     #endif
699     
700     #ifdef FBCON_HAS_CFB4
701     static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
702     	CRITFLAGS
703     	MINFO_FROM_DISP(p);
704     
705     	DBG_LOOP("matroxfb_cfb4_revc");
706     
707     	if (fontwidth(p) & 1) {
708     		fbcon_cfb4_revc(p, xx, yy);
709     		return;
710     	}
711     	yy *= fontheight(p);
712     	xx *= fontwidth(p);
713     	xx |= (xx + fontwidth(p)) << 16;
714     	xx >>= 1;
715     
716     	CRITBEGIN
717     
718     	mga_fifo(5);
719     	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
720     	mga_outl(M_FCOL, 0xFFFFFFFF);
721     	mga_outl(M_FXBNDRY, xx);
722     	mga_outl(M_YDST, yy * p->var.xres_virtual >> 6);
723     	mga_outl(M_LEN | M_EXEC, fontheight(p));
724     	WaitTillIdle();
725     
726     	CRITEND
727     }
728     #endif
729     
730     #ifdef FBCON_HAS_CFB8
731     static void matrox_cfb8_revc(struct display* p, int xx, int yy) {
732     	CRITFLAGS
733     	MINFO_FROM_DISP(p);
734     
735     	DBG_LOOP("matrox_cfb8_revc")
736     
737     	yy *= fontheight(p);
738     	xx *= fontwidth(p);
739     
740     	CRITBEGIN
741     
742     	mga_fifo(4);
743     	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
744     	mga_outl(M_FCOL, 0x0F0F0F0F);
745     	mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
746     	mga_ydstlen(yy, fontheight(p));
747     	WaitTillIdle();
748     
749     	CRITEND
750     }
751     #endif
752     
753     static void matrox_cfbX_revc(struct display* p, int xx, int yy) {
754     	CRITFLAGS
755     	MINFO_FROM_DISP(p);
756     
757     	DBG_LOOP("matrox_cfbX_revc")
758     
759     	yy *= fontheight(p);
760     	xx *= fontwidth(p);
761     
762     	CRITBEGIN
763     
764     	mga_fifo(4);
765     	mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
766     	mga_outl(M_FCOL, 0xFFFFFFFF);
767     	mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
768     	mga_ydstlen(yy, fontheight(p));
769     	WaitTillIdle();
770     
771     	CRITEND
772     }
773     
774     static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) {
775     	unsigned int bottom_height, right_width;
776     	unsigned int bottom_start, right_start;
777     	unsigned int cell_h, cell_w;
778     
779     	DBG("matrox_cfbX_clear_margins")
780     
781     	cell_w = fontwidth(p);
782     	if (!cell_w) return;	/* PARANOID */
783     	right_width = p->var.xres % cell_w;
784     	right_start = p->var.xres - right_width;
785     	if (!bottom_only && right_width) {
786     		/* clear whole right margin, not only visible portion */
787     		matroxfb_accel_clear(     PMXINFO(p)
788     			     /* color */  0x00000000,
789     			     /* y */      0,
790     			     /* x */      p->var.xoffset + right_start,
791     			     /* height */ p->var.yres_virtual,
792     			     /* width */  right_width);
793     	}
794     	cell_h = fontheight(p);
795     	if (!cell_h) return;	/* PARANOID */
796     	bottom_height = p->var.yres % cell_h;
797     	if (bottom_height) {
798     		bottom_start = p->var.yres - bottom_height;
799     		matroxfb_accel_clear(		  PMXINFO(p)
800     				     /* color */  0x00000000,
801     				     /* y */	  p->var.yoffset + bottom_start,
802     				     /* x */	  p->var.xoffset,
803     				     /* height */ bottom_height,
804     				     /* width */  right_start);
805     	}
806     }
807     
808     static void matrox_text_setup(struct display* p) {
809     	MINFO_FROM_DISP(p);
810     
811     	p->next_line = p->line_length ? p->line_length : ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
812     	p->next_plane = 0;
813     }
814     
815     static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
816     		int height, int width) {
817     	unsigned int srcoff;
818     	unsigned int dstoff;
819     	unsigned int step;
820     	CRITFLAGS
821     	MINFO_FROM_DISP(p);
822     
823     	CRITBEGIN
824     
825     	step = ACCESS_FBINFO(devflags.textstep);
826     	srcoff = (sy * p->next_line) + (sx * step);
827     	dstoff = (dy * p->next_line) + (dx * step);
828     	if (dstoff < srcoff) {
829     		while (height > 0) {
830     			int i;
831     			for (i = width; i > 0; dstoff += step, srcoff += step, i--)
832     				mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
833     			height--;
834     			dstoff += p->next_line - width * step;
835     			srcoff += p->next_line - width * step;
836     		}
837     	} else {
838     		unsigned int off;
839     
840     		off = (height - 1) * p->next_line + (width - 1) * step;
841     		srcoff += off;
842     		dstoff += off;
843     		while (height > 0) {
844     			int i;
845     			for (i = width; i > 0; dstoff -= step, srcoff -= step, i--)
846     				mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
847     			dstoff -= p->next_line - width * step;
848     			srcoff -= p->next_line - width * step;
849     			height--;
850     		}
851     	}
852     	CRITEND
853     }
854     
855     static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, int sx,
856     		int height, int width) {
857     	unsigned int offs;
858     	unsigned int val;
859     	unsigned int step;
860     	CRITFLAGS
861     	MINFO_FROM_DISP(p);
862     
863     	step = ACCESS_FBINFO(devflags.textstep);
864     	offs = sy * p->next_line + sx * step;
865     	val = ntohs((attr_bgcol(p, conp->vc_video_erase_char) << 4) | attr_fgcol(p, conp->vc_video_erase_char) | (' ' << 8));
866     
867     	CRITBEGIN
868     
869     	while (height > 0) {
870     		int i;
871     		for (i = width; i > 0; offs += step, i--)
872     			mga_writew(ACCESS_FBINFO(video.vbase), offs, val);
873     		offs += p->next_line - width * step;
874     		height--;
875     	}
876     	CRITEND
877     }
878     
879     static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
880     	unsigned int offs;
881     	unsigned int chr;
882     	unsigned int step;
883     	CRITFLAGS
884     	MINFO_FROM_DISP(p);
885     
886     	step = ACCESS_FBINFO(devflags.textstep);
887     	offs = yy * p->next_line + xx * step;
888     	chr = attr_fgcol(p,c) | (attr_bgcol(p,c) << 4) | ((c & p->charmask) << 8);
889     	if (chr & 0x10000) chr |= 0x08;
890     
891     	CRITBEGIN
892     
893     	mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(chr));
894     
895     	CRITEND
896     }
897     
898     static void matrox_text_putcs(struct vc_data* conp, struct display* p, const unsigned short* s,
899     		int count, int yy, int xx) {
900     	unsigned int offs;
901     	unsigned int attr;
902     	unsigned int step;
903     	CRITFLAGS
904     	MINFO_FROM_DISP(p);
905     
906     	step = ACCESS_FBINFO(devflags.textstep);
907     	offs = yy * p->next_line + xx * step;
908     	attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4);
909     
910     	CRITBEGIN
911     
912     	while (count-- > 0) {
913     		unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
914     		if (chr & 0x10000) chr ^= 0x10008;
915     		mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
916     		offs += step;
917     	}
918     
919     	CRITEND
920     }
921     
922     static void matrox_text_revc(struct display* p, int xx, int yy) {
923     	unsigned int offs;
924     	unsigned int step;
925     	CRITFLAGS
926     	MINFO_FROM_DISP(p);
927     
928     	step = ACCESS_FBINFO(devflags.textstep);
929     	offs = yy * p->next_line + xx * step + 1;
930     
931     	CRITBEGIN
932     
933     	mga_writeb(ACCESS_FBINFO(video.vbase), offs, mga_readb(ACCESS_FBINFO(video.vbase), offs) ^ 0x77);
934     
935     	CRITEND
936     }
937     
938     void matrox_text_createcursor(WPMINFO struct display* p) {
939     	CRITFLAGS
940     
941     	if (ACCESS_FBINFO(currcon_display) != p)
942     		return;
943     
944     	matroxfb_createcursorshape(PMINFO p, 0);
945     
946     	CRITBEGIN
947     
948     	mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
949     	mga_setr(M_CRTC_INDEX, 0x0B, ACCESS_FBINFO(cursor.d) - 1);
950     
951     	CRITEND
952     }
953     
954     static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
955     	unsigned int pos;
956     	CRITFLAGS
957     	MINFO_FROM_DISP(p);
958     
959     	if (ACCESS_FBINFO(currcon_display) != p)
960     		return;
961     
962     	if (mode == CM_ERASE) {
963     		if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
964     
965     			CRITBEGIN
966     
967     			mga_setr(M_CRTC_INDEX, 0x0A, 0x20);
968     
969     			CRITEND
970     
971     			ACCESS_FBINFO(cursor.state) = CM_ERASE;
972     		}
973     		return;
974     	}
975     	if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
976     		matrox_text_createcursor(PMINFO p);
977     
978     	/* DO NOT CHECK cursor.x != x because of matroxfb_vgaHWinit moves cursor to 0,0 */
979     	ACCESS_FBINFO(cursor.x) = x;
980     	ACCESS_FBINFO(cursor.y) = y;
981     	pos = p->next_line / ACCESS_FBINFO(devflags.textstep) * y + x;
982     
983     	CRITBEGIN
984     
985     	mga_setr(M_CRTC_INDEX, 0x0F, pos);
986     	mga_setr(M_CRTC_INDEX, 0x0E, pos >> 8);
987     
988     	mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
989     
990     	CRITEND
991     
992     	ACCESS_FBINFO(cursor.state) = CM_DRAW;
993     }
994     
995     void matrox_text_round(CPMINFO struct fb_var_screeninfo* var, struct display* p) {
996     	unsigned hf;
997     	unsigned vf;
998     	unsigned vxres;
999     	unsigned ych;
1000     
1001     	hf = fontwidth(p);
1002     	if (!hf) hf = 8;
1003     	/* do not touch xres */
1004     	vxres = (var->xres_virtual + hf - 1) / hf;
1005     	if (vxres >= 256)
1006     		vxres = 255;
1007     	if (vxres < 16)
1008     		vxres = 16;
1009     	vxres = (vxres + 1) & ~1;	/* must be even */
1010     	vf = fontheight(p);
1011     	if (!vf) vf = 16;
1012     	if (var->yres < var->yres_virtual) {
1013     		ych = ACCESS_FBINFO(devflags.textvram) / vxres;
1014     		var->yres_virtual = ych * vf;
1015     	} else
1016     		ych = var->yres_virtual / vf;
1017     	if (vxres * ych > ACCESS_FBINFO(devflags.textvram)) {
1018     		ych = ACCESS_FBINFO(devflags.textvram) / vxres;
1019     		var->yres_virtual = ych * vf;
1020     	}
1021     	var->xres_virtual = vxres * hf;
1022     }
1023     
1024     static int matrox_text_setfont(struct display* p, int width, int height) {
1025     	DBG("matrox_text_setfont");
1026     
1027     	if (p) {
1028     		MINFO_FROM_DISP(p);
1029     
1030     		matrox_text_round(PMINFO &p->var, p);
1031     		p->next_line = p->line_length = ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
1032     
1033     		if (p->conp)
1034     			matrox_text_createcursor(PMINFO p);
1035     	}
1036     	return 0;
1037     }
1038     
1039     #define matrox_cfb16_revc matrox_cfbX_revc
1040     #define matrox_cfb24_revc matrox_cfbX_revc
1041     #define matrox_cfb32_revc matrox_cfbX_revc
1042     
1043     #define matrox_cfb24_clear matrox_cfb32_clear
1044     #define matrox_cfb24_putc matrox_cfb32_putc
1045     #define matrox_cfb24_putcs matrox_cfb32_putcs
1046     
1047     #ifdef FBCON_HAS_VGATEXT
1048     static struct display_switch matroxfb_text = {
1049     	setup:		matrox_text_setup,
1050     	bmove:		matrox_text_bmove,
1051     	clear:		matrox_text_clear,
1052     	putc:		matrox_text_putc,
1053     	putcs:		matrox_text_putcs,
1054     	revc:		matrox_text_revc,
1055     	cursor:		matrox_text_cursor,
1056     	set_font:	matrox_text_setfont,
1057     	fontwidthmask:	FONTWIDTH(8)|FONTWIDTH(9)
1058     };
1059     #endif
1060     
1061     #ifdef FBCON_HAS_CFB4
1062     static struct display_switch matroxfb_cfb4 = {
1063     	setup:		fbcon_cfb4_setup,
1064     	bmove:		matrox_cfb4_bmove,
1065     	clear:		matrox_cfb4_clear,
1066     	putc:		fbcon_cfb4_putc,
1067     	putcs:		fbcon_cfb4_putcs,
1068     	revc:		matrox_cfb4_revc,
1069     	fontwidthmask:	FONTWIDTH(8) /* fix, fix, fix it */
1070     };
1071     #endif
1072     
1073     #ifdef FBCON_HAS_CFB8
1074     static struct display_switch matroxfb_cfb8 = {
1075     	setup:		fbcon_cfb8_setup,
1076     	bmove:		matrox_cfbX_bmove,
1077     	clear:		matrox_cfb8_clear,
1078     	putc:		matrox_cfb8_putc,
1079     	putcs:		matrox_cfb8_putcs,
1080     	revc:		matrox_cfb8_revc,
1081     	clear_margins:	matrox_cfbX_clear_margins,
1082     	fontwidthmask:	~1 /* FONTWIDTHS */
1083     };
1084     #endif
1085     
1086     #ifdef FBCON_HAS_CFB16
1087     static struct display_switch matroxfb_cfb16 = {
1088     	setup:		fbcon_cfb16_setup,
1089     	bmove:		matrox_cfbX_bmove,
1090     	clear:		matrox_cfb16_clear,
1091     	putc:		matrox_cfb16_putc,
1092     	putcs:		matrox_cfb16_putcs,
1093     	revc:		matrox_cfb16_revc,
1094     	clear_margins:	matrox_cfbX_clear_margins,
1095     	fontwidthmask:	~1 /* FONTWIDTHS */
1096     };
1097     #endif
1098     
1099     #ifdef FBCON_HAS_CFB24
1100     static struct display_switch matroxfb_cfb24 = {
1101     	setup:		fbcon_cfb24_setup,
1102     	bmove:		matrox_cfbX_bmove,
1103     	clear:		matrox_cfb24_clear,
1104     	putc:		matrox_cfb24_putc,
1105     	putcs:		matrox_cfb24_putcs,
1106     	revc:		matrox_cfb24_revc,
1107     	clear_margins:	matrox_cfbX_clear_margins,
1108     	fontwidthmask:	~1 /* FONTWIDTHS */ /* TODO: and what about non-aligned access on BE? I think that there are no in my code */
1109     };
1110     #endif
1111     
1112     #ifdef FBCON_HAS_CFB32
1113     static struct display_switch matroxfb_cfb32 = {
1114     	setup:		fbcon_cfb32_setup,
1115     	bmove:		matrox_cfbX_bmove,
1116     	clear:		matrox_cfb32_clear,
1117     	putc:		matrox_cfb32_putc,
1118     	putcs:		matrox_cfb32_putcs,
1119     	revc:		matrox_cfb32_revc,
1120     	clear_margins:	matrox_cfbX_clear_margins,
1121     	fontwidthmask:	~1 /* FONTWIDTHS */
1122     };
1123     #endif
1124     
1125     void initMatrox(WPMINFO struct display* p) {
1126     	struct display_switch *swtmp;
1127     
1128     	DBG("initMatrox")
1129     
1130     	if (ACCESS_FBINFO(currcon_display) != p)
1131     		return;
1132     	if (p->dispsw && p->conp)
1133     		fb_con.con_cursor(p->conp, CM_ERASE);
1134     	p->dispsw_data = NULL;
1135     	if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
1136     		if (p->type == FB_TYPE_TEXT) {
1137     			swtmp = &matroxfb_text;
1138     		} else {
1139     			switch (p->var.bits_per_pixel) {
1140     #ifdef FBCON_HAS_CFB4
1141     			case 4:
1142     				swtmp = &fbcon_cfb4;
1143     				break;
1144     #endif
1145     #ifdef FBCON_HAS_CFB8
1146     			case 8:
1147     				swtmp = &fbcon_cfb8;
1148     				break;
1149     #endif
1150     #ifdef FBCON_HAS_CFB16
1151     			case 16:
1152     				p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
1153     				swtmp = &fbcon_cfb16;
1154     				break;
1155     #endif
1156     #ifdef FBCON_HAS_CFB24
1157     			case 24:
1158     				p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
1159     				swtmp = &fbcon_cfb24;
1160     				break;
1161     #endif
1162     #ifdef FBCON_HAS_CFB32
1163     			case 32:
1164     				p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
1165     				swtmp = &fbcon_cfb32;
1166     				break;
1167     #endif
1168     			default:
1169     				p->dispsw = &fbcon_dummy;
1170     				return;
1171     			}
1172     		}
1173     		dprintk(KERN_INFO "matroxfb: acceleration disabled\n");
1174     	} else if (p->type == FB_TYPE_TEXT) {
1175     		swtmp = &matroxfb_text;
1176     	} else {
1177     		switch (p->var.bits_per_pixel) {
1178     #ifdef FBCON_HAS_CFB4
1179     		case 4:
1180     			swtmp = &matroxfb_cfb4;
1181     			break;
1182     #endif
1183     #ifdef FBCON_HAS_CFB8
1184     		case 8:
1185     			swtmp = &matroxfb_cfb8;
1186     			break;
1187     #endif
1188     #ifdef FBCON_HAS_CFB16
1189     		case 16:
1190     			p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
1191     			swtmp = &matroxfb_cfb16;
1192     			break;
1193     #endif
1194     #ifdef FBCON_HAS_CFB24
1195     		case 24:
1196     			p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
1197     			swtmp = &matroxfb_cfb24;
1198     			break;
1199     #endif
1200     #ifdef FBCON_HAS_CFB32
1201     		case 32:
1202     			p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
1203     			swtmp = &matroxfb_cfb32;
1204     			break;
1205     #endif
1206     		default:
1207     			p->dispsw = &fbcon_dummy;
1208     			return;
1209     		}
1210     	}
1211     	memcpy(&ACCESS_FBINFO(dispsw), swtmp, sizeof(ACCESS_FBINFO(dispsw)));
1212     	p->dispsw = &ACCESS_FBINFO(dispsw);
1213     	if ((p->type != FB_TYPE_TEXT) && ACCESS_FBINFO(devflags.hwcursor)) {
1214     		ACCESS_FBINFO(hw_switch)->selhwcursor(PMINFO p);
1215     	}
1216     }
1217     
1218     void matrox_init_putc(WPMINFO struct display* p, void (*dac_createcursor)(WPMINFO struct display* p)) {
1219     	int i;
1220     
1221     	if (p && p->conp) {
1222     		if (p->type == FB_TYPE_TEXT) {
1223     			matrox_text_createcursor(PMINFO p);
1224     			matrox_text_loadfont(PMINFO p);
1225     			i = 0;
1226     		} else {
1227     			dac_createcursor(PMINFO p);
1228     			i = matroxfb_fastfont_tryset(PMINFO p);
1229     		}
1230     	} else
1231     		i = 0;
1232     	if (i) {
1233     		ACCESS_FBINFO(curr.putc) = matrox_cfbX_fastputc;
1234     		ACCESS_FBINFO(curr.putcs) = matrox_cfbX_fastputcs;
1235     	} else {
1236     		ACCESS_FBINFO(curr.putc) = matrox_cfbX_putc;
1237     		ACCESS_FBINFO(curr.putcs) = matrox_cfbX_putcs;
1238     	}
1239     }
1240