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