Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
489 | giacomo | 1 | /* |
2 | * |
||
3 | * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 |
||
4 | * |
||
5 | * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> |
||
6 | * |
||
7 | * Version: 1.65 2002/08/14 |
||
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 <linuxcomp.h> |
||
80 | |||
81 | #include "matroxfb_accel.h" |
||
82 | #include "matroxfb_DAC1064.h" |
||
83 | #include "matroxfb_Ti3026.h" |
||
84 | #include "matroxfb_misc.h" |
||
85 | |||
86 | #define curr_ydstorg(x) ACCESS_FBINFO2(x, curr.ydstorg.pixels) |
||
87 | |||
88 | #define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l)) |
||
89 | |||
90 | static inline void matrox_cfb4_pal(u_int32_t* pal) { |
||
91 | unsigned int i; |
||
92 | |||
93 | for (i = 0; i < 16; i++) { |
||
94 | pal[i] = i * 0x11111111U; |
||
95 | } |
||
96 | pal[i] = 0xFFFFFFFF; |
||
97 | } |
||
98 | |||
99 | static inline void matrox_cfb8_pal(u_int32_t* pal) { |
||
100 | unsigned int i; |
||
101 | |||
102 | for (i = 0; i < 16; i++) { |
||
103 | pal[i] = i * 0x01010101U; |
||
104 | } |
||
105 | pal[i] = 0x0F0F0F0F; |
||
106 | } |
||
107 | |||
108 | static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area); |
||
109 | static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect); |
||
110 | static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image); |
||
111 | static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect); |
||
112 | static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area); |
||
113 | |||
114 | void matrox_cfbX_init(WPMINFO2) { |
||
115 | u_int32_t maccess; |
||
116 | u_int32_t mpitch; |
||
117 | u_int32_t mopmode; |
||
118 | int accel; |
||
119 | |||
120 | DBG(__FUNCTION__) |
||
121 | |||
122 | mpitch = ACCESS_FBINFO(fbcon).var.xres_virtual; |
||
123 | |||
124 | ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea; |
||
125 | ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect; |
||
126 | ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit; |
||
127 | ACCESS_FBINFO(fbops).fb_cursor = soft_cursor; |
||
128 | |||
129 | accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; |
||
130 | |||
131 | switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { |
||
132 | case 4: maccess = 0x00000000; /* accelerate as 8bpp video */ |
||
133 | mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */ |
||
134 | mopmode = M_OPMODE_4BPP; |
||
135 | matrox_cfb4_pal(ACCESS_FBINFO(cmap)); |
||
136 | if (accel && !(mpitch & 1)) { |
||
137 | ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_cfb4_copyarea; |
||
138 | ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_cfb4_fillrect; |
||
139 | } |
||
140 | break; |
||
141 | case 8: maccess = 0x00000000; |
||
142 | mopmode = M_OPMODE_8BPP; |
||
143 | matrox_cfb8_pal(ACCESS_FBINFO(cmap)); |
||
144 | if (accel) { |
||
145 | ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; |
||
146 | ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; |
||
147 | ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; |
||
148 | } |
||
149 | break; |
||
150 | case 16: if (ACCESS_FBINFO(fbcon).var.green.length == 5) { |
||
151 | maccess = 0xC0000001; |
||
152 | ACCESS_FBINFO(cmap[16]) = 0x7FFF7FFF; |
||
153 | } else { |
||
154 | maccess = 0x40000001; |
||
155 | ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF; |
||
156 | } |
||
157 | mopmode = M_OPMODE_16BPP; |
||
158 | if (accel) { |
||
159 | ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; |
||
160 | ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; |
||
161 | ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; |
||
162 | } |
||
163 | break; |
||
164 | case 24: maccess = 0x00000003; |
||
165 | mopmode = M_OPMODE_24BPP; |
||
166 | ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF; |
||
167 | if (accel) { |
||
168 | ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; |
||
169 | ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; |
||
170 | ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; |
||
171 | } |
||
172 | break; |
||
173 | case 32: maccess = 0x00000002; |
||
174 | mopmode = M_OPMODE_32BPP; |
||
175 | ACCESS_FBINFO(cmap[16]) = 0xFFFFFFFF; |
||
176 | if (accel) { |
||
177 | ACCESS_FBINFO(fbops).fb_copyarea = matroxfb_copyarea; |
||
178 | ACCESS_FBINFO(fbops).fb_fillrect = matroxfb_fillrect; |
||
179 | ACCESS_FBINFO(fbops).fb_imageblit = matroxfb_imageblit; |
||
180 | } |
||
181 | break; |
||
182 | default: maccess = 0x00000000; |
||
183 | mopmode = 0x00000000; |
||
184 | break; /* turn off acceleration!!! */ |
||
185 | } |
||
186 | mga_fifo(8); |
||
187 | mga_outl(M_PITCH, mpitch); |
||
188 | mga_outl(M_YDSTORG, curr_ydstorg(MINFO)); |
||
189 | if (ACCESS_FBINFO(capable.plnwt)) |
||
190 | mga_outl(M_PLNWT, -1); |
||
191 | if (ACCESS_FBINFO(capable.srcorg)) { |
||
192 | mga_outl(M_SRCORG, 0); |
||
193 | mga_outl(M_DSTORG, 0); |
||
194 | } |
||
195 | mga_outl(M_OPMODE, mopmode); |
||
196 | mga_outl(M_CXBNDRY, 0xFFFF0000); |
||
197 | mga_outl(M_YTOP, 0); |
||
198 | mga_outl(M_YBOT, 0x01FFFFFF); |
||
199 | mga_outl(M_MACCESS, maccess); |
||
200 | ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO; |
||
201 | if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC; |
||
202 | ACCESS_FBINFO(accel.m_opmode) = mopmode; |
||
203 | } |
||
204 | |||
205 | EXPORT_SYMBOL(matrox_cfbX_init); |
||
206 | |||
207 | static void matrox_accel_bmove(WPMINFO int vxres, int sy, int sx, int dy, int dx, int height, int width) { |
||
208 | int start, end; |
||
209 | CRITFLAGS |
||
210 | |||
211 | DBG(__FUNCTION__) |
||
212 | |||
213 | CRITBEGIN |
||
214 | |||
215 | if ((dy < sy) || ((dy == sy) && (dx <= sx))) { |
||
216 | mga_fifo(2); |
||
217 | mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO | |
||
218 | M_DWG_BFCOL | M_DWG_REPLACE); |
||
219 | mga_outl(M_AR5, vxres); |
||
220 | width--; |
||
221 | start = sy*vxres+sx+curr_ydstorg(MINFO); |
||
222 | end = start+width; |
||
223 | } else { |
||
224 | mga_fifo(3); |
||
225 | mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE); |
||
226 | mga_outl(M_SGN, 5); |
||
227 | mga_outl(M_AR5, -vxres); |
||
228 | width--; |
||
229 | end = (sy+height-1)*vxres+sx+curr_ydstorg(MINFO); |
||
230 | start = end+width; |
||
231 | dy += height-1; |
||
232 | } |
||
233 | mga_fifo(4); |
||
234 | mga_outl(M_AR0, end); |
||
235 | mga_outl(M_AR3, start); |
||
236 | mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx); |
||
237 | mga_ydstlen(dy, height); |
||
238 | WaitTillIdle(); |
||
239 | |||
240 | CRITEND |
||
241 | } |
||
242 | |||
243 | static void matrox_accel_bmove_lin(WPMINFO int vxres, int sy, int sx, int dy, int dx, int height, int width) { |
||
244 | int start, end; |
||
245 | CRITFLAGS |
||
246 | |||
247 | DBG(__FUNCTION__) |
||
248 | |||
249 | CRITBEGIN |
||
250 | |||
251 | if ((dy < sy) || ((dy == sy) && (dx <= sx))) { |
||
252 | mga_fifo(2); |
||
253 | mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO | |
||
254 | M_DWG_BFCOL | M_DWG_REPLACE); |
||
255 | mga_outl(M_AR5, vxres); |
||
256 | width--; |
||
257 | start = sy*vxres+sx+curr_ydstorg(MINFO); |
||
258 | end = start+width; |
||
259 | } else { |
||
260 | mga_fifo(3); |
||
261 | mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE); |
||
262 | mga_outl(M_SGN, 5); |
||
263 | mga_outl(M_AR5, -vxres); |
||
264 | width--; |
||
265 | end = (sy+height-1)*vxres+sx+curr_ydstorg(MINFO); |
||
266 | start = end+width; |
||
267 | dy += height-1; |
||
268 | } |
||
269 | mga_fifo(5); |
||
270 | mga_outl(M_AR0, end); |
||
271 | mga_outl(M_AR3, start); |
||
272 | mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx); |
||
273 | mga_outl(M_YDST, dy*vxres >> 5); |
||
274 | mga_outl(M_LEN | M_EXEC, height); |
||
275 | WaitTillIdle(); |
||
276 | |||
277 | CRITEND |
||
278 | } |
||
279 | |||
280 | static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) { |
||
281 | MINFO_FROM_INFO(info); |
||
282 | |||
283 | if ((area->sx | area->dx | area->width) & 1) |
||
284 | cfb_copyarea(info, area); |
||
285 | else |
||
286 | matrox_accel_bmove_lin(PMINFO ACCESS_FBINFO(fbcon.var.xres_virtual) >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1); |
||
287 | } |
||
288 | |||
289 | static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) { |
||
290 | MINFO_FROM_INFO(info); |
||
291 | |||
292 | matrox_accel_bmove(PMINFO ACCESS_FBINFO(fbcon.var.xres_virtual), area->sy, area->sx, area->dy, area->dx, area->height, area->width); |
||
293 | } |
||
294 | |||
295 | static void matroxfb_accel_clear(WPMINFO u_int32_t color, int sy, int sx, int height, |
||
296 | int width) { |
||
297 | CRITFLAGS |
||
298 | |||
299 | DBG(__FUNCTION__) |
||
300 | |||
301 | CRITBEGIN |
||
302 | |||
303 | mga_fifo(5); |
||
304 | mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE); |
||
305 | mga_outl(M_FCOL, color); |
||
306 | mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); |
||
307 | mga_ydstlen(sy, height); |
||
308 | WaitTillIdle(); |
||
309 | |||
310 | CRITEND |
||
311 | } |
||
312 | |||
313 | static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { |
||
314 | MINFO_FROM_INFO(info); |
||
315 | |||
316 | switch (rect->rop) { |
||
317 | case ROP_COPY: |
||
318 | matroxfb_accel_clear(PMINFO ((u_int32_t*)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); |
||
319 | break; |
||
320 | } |
||
321 | } |
||
322 | |||
323 | static void matroxfb_cfb4_clear(WPMINFO u_int32_t bgx, int sy, int sx, int height, int width) { |
||
324 | int whattodo; |
||
325 | CRITFLAGS |
||
326 | |||
327 | DBG(__FUNCTION__) |
||
328 | |||
329 | CRITBEGIN |
||
330 | |||
331 | whattodo = 0; |
||
332 | if (sx & 1) { |
||
333 | sx ++; |
||
334 | if (!width) return; |
||
335 | width --; |
||
336 | whattodo = 1; |
||
337 | } |
||
338 | if (width & 1) { |
||
339 | whattodo |= 2; |
||
340 | } |
||
341 | width >>= 1; |
||
342 | sx >>= 1; |
||
343 | if (width) { |
||
344 | mga_fifo(5); |
||
345 | mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE2); |
||
346 | mga_outl(M_FCOL, bgx); |
||
347 | mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); |
||
348 | mga_outl(M_YDST, sy * ACCESS_FBINFO(fbcon).var.xres_virtual >> 6); |
||
349 | mga_outl(M_LEN | M_EXEC, height); |
||
350 | WaitTillIdle(); |
||
351 | } |
||
352 | if (whattodo) { |
||
353 | u_int32_t step = ACCESS_FBINFO(fbcon).var.xres_virtual >> 1; |
||
354 | vaddr_t vbase = ACCESS_FBINFO(video.vbase); |
||
355 | if (whattodo & 1) { |
||
356 | unsigned int uaddr = sy * step + sx - 1; |
||
357 | u_int32_t loop; |
||
358 | u_int8_t bgx2 = bgx & 0xF0; |
||
359 | for (loop = height; loop > 0; loop --) { |
||
360 | mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2); |
||
361 | uaddr += step; |
||
362 | } |
||
363 | } |
||
364 | if (whattodo & 2) { |
||
365 | unsigned int uaddr = sy * step + sx + width; |
||
366 | u_int32_t loop; |
||
367 | u_int8_t bgx2 = bgx & 0x0F; |
||
368 | for (loop = height; loop > 0; loop --) { |
||
369 | mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2); |
||
370 | uaddr += step; |
||
371 | } |
||
372 | } |
||
373 | } |
||
374 | |||
375 | CRITEND |
||
376 | } |
||
377 | |||
378 | static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) { |
||
379 | MINFO_FROM_INFO(info); |
||
380 | |||
381 | switch (rect->rop) { |
||
382 | case ROP_COPY: |
||
383 | matroxfb_cfb4_clear(PMINFO ((u_int32_t*)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width); |
||
384 | break; |
||
385 | } |
||
386 | } |
||
387 | |||
388 | static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx, |
||
389 | const u_int8_t* chardata, int width, int height, int yy, int xx) { |
||
390 | u_int32_t step; |
||
391 | u_int32_t ydstlen; |
||
392 | u_int32_t xlen; |
||
393 | u_int32_t ar0; |
||
394 | u_int32_t charcell; |
||
395 | u_int32_t fxbndry; |
||
396 | vaddr_t mmio; |
||
397 | int easy; |
||
398 | CRITFLAGS |
||
399 | |||
400 | DBG_HEAVY(__FUNCTION__); |
||
401 | |||
402 | step = (width + 7) >> 3; |
||
403 | charcell = height * step; |
||
404 | xlen = (charcell + 3) & ~3; |
||
405 | ydstlen = (yy << 16) | height; |
||
406 | if (width == step << 3) { |
||
407 | ar0 = height * width - 1; |
||
408 | easy = 1; |
||
409 | } else { |
||
410 | ar0 = width - 1; |
||
411 | easy = 0; |
||
412 | } |
||
413 | |||
414 | CRITBEGIN |
||
415 | |||
416 | #ifdef __BIG_ENDIAN |
||
417 | WaitTillIdle(); |
||
418 | mga_outl(M_OPMODE, M_OPMODE_8BPP); |
||
419 | #else |
||
420 | mga_fifo(3); |
||
421 | #endif |
||
422 | if (easy) |
||
423 | mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE); |
||
424 | else |
||
425 | mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE); |
||
426 | mga_outl(M_FCOL, fgx); |
||
427 | mga_outl(M_BCOL, bgx); |
||
428 | fxbndry = ((xx + width - 1) << 16) | xx; |
||
429 | mmio = ACCESS_FBINFO(mmio.vbase); |
||
430 | |||
431 | mga_fifo(6); |
||
432 | mga_writel(mmio, M_FXBNDRY, fxbndry); |
||
433 | mga_writel(mmio, M_AR0, ar0); |
||
434 | mga_writel(mmio, M_AR3, 0); |
||
435 | if (easy) { |
||
436 | mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen); |
||
437 | mga_memcpy_toio(mmio, 0, chardata, xlen); |
||
438 | } else { |
||
439 | mga_writel(mmio, M_AR5, 0); |
||
440 | mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen); |
||
441 | if ((step & 3) == 0) { |
||
442 | /* Great. Source has 32bit aligned lines, so we can feed them |
||
443 | directly to the accelerator. */ |
||
444 | mga_memcpy_toio(mmio, 0, chardata, charcell); |
||
445 | } else if (step == 1) { |
||
446 | /* Special case for 1..8bit widths */ |
||
447 | while (height--) { |
||
448 | #ifdef __LITTLE_ENDIAN |
||
449 | mga_writel(mmio, 0, *chardata); |
||
450 | #else |
||
451 | mga_writel(mmio, 0, (*chardata) << 24); |
||
452 | #endif |
||
453 | chardata++; |
||
454 | } |
||
455 | } else if (step == 2) { |
||
456 | /* Special case for 9..15bit widths */ |
||
457 | while (height--) { |
||
458 | #ifdef __LITTLE_ENDIAN |
||
459 | mga_writel(mmio, 0, *(u_int16_t*)chardata); |
||
460 | #else |
||
461 | mga_writel(mmio, 0, (*(u_int16_t*)chardata) << 16); |
||
462 | #endif |
||
463 | chardata += 2; |
||
464 | } |
||
465 | } else { |
||
466 | /* Tell... well, why bother... */ |
||
467 | while (height--) { |
||
468 | size_t i; |
||
469 | |||
470 | for (i = 0; i < step; i += 4) { |
||
471 | /* Hope that there are at least three readable bytes beyond the end of bitmap */ |
||
472 | mga_writel(mmio, 0, get_unaligned((u_int32_t*)(chardata + i))); |
||
473 | } |
||
474 | chardata += step; |
||
475 | } |
||
476 | } |
||
477 | } |
||
478 | WaitTillIdle(); |
||
479 | #ifdef __BIG_ENDIAN |
||
480 | mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode)); |
||
481 | #endif |
||
482 | CRITEND |
||
483 | } |
||
484 | |||
485 | |||
486 | static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) { |
||
487 | MINFO_FROM_INFO(info); |
||
488 | |||
489 | DBG_HEAVY(__FUNCTION__); |
||
490 | |||
491 | if (image->depth == 0) { |
||
492 | u_int32_t fgx, bgx; |
||
493 | |||
494 | fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color]; |
||
495 | bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color]; |
||
496 | matroxfb_1bpp_imageblit(PMINFO fgx, bgx, image->data, image->width, image->height, image->dy, image->dx); |
||
497 | } else { |
||
498 | /* Danger! image->depth is useless: logo painting code always |
||
499 | passes framebuffer color depth here, although logo data are |
||
500 | always 8bpp and info->pseudo_palette is changed to contain |
||
501 | logo palette to be used (but only for true/direct-color... sic...). |
||
502 | So do it completely in software... */ |
||
503 | cfb_imageblit(info, image); |
||
504 | } |
||
505 | } |
||
506 | |||
507 | MODULE_LICENSE("GPL"); |