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