diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2008-07-24 00:31:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:36 -0400 |
commit | 49b1f4b44bcdc47a10d2b354b269305043ef2a32 (patch) | |
tree | cad5923a13f7fd051fd7d7b903778ce36f9985e8 /drivers/video/tridentfb.c | |
parent | bcac2d5fe36238dcfc955b49f9db10ad3ae3e53c (diff) |
tridentfb: acceleration code improvements
This patch brings various acceleration improvements:
- set copyarea/fillrect for non-accelerated framebuffer (fix)
- remove 15 bpp depth handling to simplify code as it hardly
works (15 bpp handling was obviously missing in some switches)
- add fb_sync call and move waiting before accelerated function
to make acceleration more asynchronous to cpu (few % of speed
improvement)
- add cpu_relax() call in waiting loops
- make longer register names and name more registers
- move registers' definition to header
- general code improvements (shortening, simplifying)
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/tridentfb.c')
-rw-r--r-- | drivers/video/tridentfb.c | 261 |
1 files changed, 89 insertions, 172 deletions
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 9b87c08e517d..4a1258f9509e 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Frame buffer driver for Trident Blade and Image series | 2 | * Frame buffer driver for Trident TGUI, Blade and Image series |
3 | * | 3 | * |
4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> | 4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> |
5 | * | 5 | * |
@@ -13,7 +13,6 @@ | |||
13 | * code, suggestions | 13 | * code, suggestions |
14 | * TODO: | 14 | * TODO: |
15 | * timing value tweaking so it looks good on every monitor in every mode | 15 | * timing value tweaking so it looks good on every monitor in every mode |
16 | * TGUI acceleration | ||
17 | */ | 16 | */ |
18 | 17 | ||
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
@@ -193,37 +192,13 @@ static inline u32 readmmr(struct tridentfb_par *par, u16 r) | |||
193 | */ | 192 | */ |
194 | 193 | ||
195 | #define point(x, y) ((y) << 16 | (x)) | 194 | #define point(x, y) ((y) << 16 | (x)) |
196 | #define STA 0x2120 | ||
197 | #define CMD 0x2144 | ||
198 | #define ROP 0x2148 | ||
199 | #define CLR 0x2160 | ||
200 | #define SR1 0x2100 | ||
201 | #define SR2 0x2104 | ||
202 | #define DR1 0x2108 | ||
203 | #define DR2 0x210C | ||
204 | |||
205 | #define ROP_S 0xCC | ||
206 | 195 | ||
207 | static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp) | 196 | static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
208 | { | 197 | { |
209 | int v1 = (pitch >> 3) << 20; | 198 | int v1 = (pitch >> 3) << 20; |
210 | int tmp = 0, v2; | 199 | int tmp = bpp == 24 ? 2 : (bpp >> 4); |
211 | switch (bpp) { | 200 | int v2 = v1 | (tmp << 29); |
212 | case 8: | 201 | |
213 | tmp = 0; | ||
214 | break; | ||
215 | case 15: | ||
216 | tmp = 5; | ||
217 | break; | ||
218 | case 16: | ||
219 | tmp = 1; | ||
220 | break; | ||
221 | case 24: | ||
222 | case 32: | ||
223 | tmp = 2; | ||
224 | break; | ||
225 | } | ||
226 | v2 = v1 | (tmp << 29); | ||
227 | writemmr(par, 0x21C0, v2); | 202 | writemmr(par, 0x21C0, v2); |
228 | writemmr(par, 0x21C4, v2); | 203 | writemmr(par, 0x21C4, v2); |
229 | writemmr(par, 0x21B8, v2); | 204 | writemmr(par, 0x21B8, v2); |
@@ -237,29 +212,29 @@ static void blade_init_accel(struct tridentfb_par *par, int pitch, int bpp) | |||
237 | 212 | ||
238 | static void blade_wait_engine(struct tridentfb_par *par) | 213 | static void blade_wait_engine(struct tridentfb_par *par) |
239 | { | 214 | { |
240 | while (readmmr(par, STA) & 0xFA800000) ; | 215 | while (readmmr(par, STATUS) & 0xFA800000) |
216 | cpu_relax(); | ||
241 | } | 217 | } |
242 | 218 | ||
243 | static void blade_fill_rect(struct tridentfb_par *par, | 219 | static void blade_fill_rect(struct tridentfb_par *par, |
244 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | 220 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) |
245 | { | 221 | { |
246 | writemmr(par, CLR, c); | 222 | writemmr(par, COLOR, c); |
247 | writemmr(par, ROP, rop ? 0x66 : ROP_S); | 223 | writemmr(par, ROP, rop ? ROP_X : ROP_S); |
248 | writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); | 224 | writemmr(par, CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); |
249 | 225 | ||
250 | writemmr(par, DR1, point(x, y)); | 226 | writemmr(par, DST1, point(x, y)); |
251 | writemmr(par, DR2, point(x + w - 1, y + h - 1)); | 227 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); |
252 | } | 228 | } |
253 | 229 | ||
254 | static void blade_copy_rect(struct tridentfb_par *par, | 230 | static void blade_copy_rect(struct tridentfb_par *par, |
255 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | 231 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) |
256 | { | 232 | { |
257 | u32 s1, s2, d1, d2; | ||
258 | int direction = 2; | 233 | int direction = 2; |
259 | s1 = point(x1, y1); | 234 | u32 s1 = point(x1, y1); |
260 | s2 = point(x1 + w - 1, y1 + h - 1); | 235 | u32 s2 = point(x1 + w - 1, y1 + h - 1); |
261 | d1 = point(x2, y2); | 236 | u32 d1 = point(x2, y2); |
262 | d2 = point(x2 + w - 1, y2 + h - 1); | 237 | u32 d2 = point(x2 + w - 1, y2 + h - 1); |
263 | 238 | ||
264 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) | 239 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) |
265 | direction = 0; | 240 | direction = 0; |
@@ -267,38 +242,20 @@ static void blade_copy_rect(struct tridentfb_par *par, | |||
267 | writemmr(par, ROP, ROP_S); | 242 | writemmr(par, ROP, ROP_S); |
268 | writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction); | 243 | writemmr(par, CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction); |
269 | 244 | ||
270 | writemmr(par, SR1, direction ? s2 : s1); | 245 | writemmr(par, SRC1, direction ? s2 : s1); |
271 | writemmr(par, SR2, direction ? s1 : s2); | 246 | writemmr(par, SRC2, direction ? s1 : s2); |
272 | writemmr(par, DR1, direction ? d2 : d1); | 247 | writemmr(par, DST1, direction ? d2 : d1); |
273 | writemmr(par, DR2, direction ? d1 : d2); | 248 | writemmr(par, DST2, direction ? d1 : d2); |
274 | } | 249 | } |
275 | 250 | ||
276 | /* | 251 | /* |
277 | * BladeXP specific acceleration functions | 252 | * BladeXP specific acceleration functions |
278 | */ | 253 | */ |
279 | 254 | ||
280 | #define ROP_P 0xF0 | ||
281 | #define masked_point(x, y) ((y & 0xffff)<<16|(x & 0xffff)) | ||
282 | |||
283 | static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp) | 255 | static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
284 | { | 256 | { |
285 | int tmp = 0, v1; | 257 | unsigned char x = bpp == 24 ? 3 : (bpp >> 4); |
286 | unsigned char x = 0; | 258 | int v1 = pitch << (bpp == 24 ? 20 : (18 + x)); |
287 | |||
288 | switch (bpp) { | ||
289 | case 8: | ||
290 | x = 0; | ||
291 | break; | ||
292 | case 16: | ||
293 | x = 1; | ||
294 | break; | ||
295 | case 24: | ||
296 | x = 3; | ||
297 | break; | ||
298 | case 32: | ||
299 | x = 2; | ||
300 | break; | ||
301 | } | ||
302 | 259 | ||
303 | switch (pitch << (bpp >> 3)) { | 260 | switch (pitch << (bpp >> 3)) { |
304 | case 8192: | 261 | case 8192: |
@@ -320,22 +277,6 @@ static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp) | |||
320 | 277 | ||
321 | eng_oper = x | 0x40; | 278 | eng_oper = x | 0x40; |
322 | 279 | ||
323 | switch (bpp) { | ||
324 | case 8: | ||
325 | tmp = 18; | ||
326 | break; | ||
327 | case 15: | ||
328 | case 16: | ||
329 | tmp = 19; | ||
330 | break; | ||
331 | case 24: | ||
332 | case 32: | ||
333 | tmp = 20; | ||
334 | break; | ||
335 | } | ||
336 | |||
337 | v1 = pitch << tmp; | ||
338 | |||
339 | writemmr(par, 0x2154, v1); | 280 | writemmr(par, 0x2154, v1); |
340 | writemmr(par, 0x2150, v1); | 281 | writemmr(par, 0x2150, v1); |
341 | t_outb(par, 3, 0x2126); | 282 | t_outb(par, 3, 0x2126); |
@@ -343,15 +284,11 @@ static void xp_init_accel(struct tridentfb_par *par, int pitch, int bpp) | |||
343 | 284 | ||
344 | static void xp_wait_engine(struct tridentfb_par *par) | 285 | static void xp_wait_engine(struct tridentfb_par *par) |
345 | { | 286 | { |
346 | int busy; | ||
347 | int count, timeout; | 287 | int count, timeout; |
348 | 288 | ||
349 | count = 0; | 289 | count = 0; |
350 | timeout = 0; | 290 | timeout = 0; |
351 | for (;;) { | 291 | while (t_inb(par, STATUS) & 0x80) { |
352 | busy = t_inb(par, STA) & 0x80; | ||
353 | if (busy != 0x80) | ||
354 | return; | ||
355 | count++; | 292 | count++; |
356 | if (count == 10000000) { | 293 | if (count == 10000000) { |
357 | /* Timeout */ | 294 | /* Timeout */ |
@@ -359,10 +296,11 @@ static void xp_wait_engine(struct tridentfb_par *par) | |||
359 | timeout++; | 296 | timeout++; |
360 | if (timeout == 8) { | 297 | if (timeout == 8) { |
361 | /* Reset engine */ | 298 | /* Reset engine */ |
362 | t_outb(par, 0x00, 0x2120); | 299 | t_outb(par, 0x00, STATUS); |
363 | return; | 300 | return; |
364 | } | 301 | } |
365 | } | 302 | } |
303 | cpu_relax(); | ||
366 | } | 304 | } |
367 | } | 305 | } |
368 | 306 | ||
@@ -371,10 +309,10 @@ static void xp_fill_rect(struct tridentfb_par *par, | |||
371 | { | 309 | { |
372 | writemmr(par, 0x2127, ROP_P); | 310 | writemmr(par, 0x2127, ROP_P); |
373 | writemmr(par, 0x2158, c); | 311 | writemmr(par, 0x2158, c); |
374 | writemmr(par, 0x2128, 0x4000); | 312 | writemmr(par, DRAWFL, 0x4000); |
375 | writemmr(par, 0x2140, masked_point(h, w)); | 313 | writemmr(par, OLDDIM, point(h, w)); |
376 | writemmr(par, 0x2138, masked_point(y, x)); | 314 | writemmr(par, OLDDST, point(y, x)); |
377 | t_outb(par, 0x01, 0x2124); | 315 | t_outb(par, 0x01, OLDCMD); |
378 | t_outb(par, eng_oper, 0x2125); | 316 | t_outb(par, eng_oper, 0x2125); |
379 | } | 317 | } |
380 | 318 | ||
@@ -404,12 +342,12 @@ static void xp_copy_rect(struct tridentfb_par *par, | |||
404 | y2_tmp = y2; | 342 | y2_tmp = y2; |
405 | } | 343 | } |
406 | 344 | ||
407 | writemmr(par, 0x2128, direction); | 345 | writemmr(par, DRAWFL, direction); |
408 | t_outb(par, ROP_S, 0x2127); | 346 | t_outb(par, ROP_S, 0x2127); |
409 | writemmr(par, 0x213C, masked_point(y1_tmp, x1_tmp)); | 347 | writemmr(par, OLDSRC, point(y1_tmp, x1_tmp)); |
410 | writemmr(par, 0x2138, masked_point(y2_tmp, x2_tmp)); | 348 | writemmr(par, OLDDST, point(y2_tmp, x2_tmp)); |
411 | writemmr(par, 0x2140, masked_point(h, w)); | 349 | writemmr(par, OLDDIM, point(h, w)); |
412 | t_outb(par, 0x01, 0x2124); | 350 | t_outb(par, 0x01, OLDCMD); |
413 | } | 351 | } |
414 | 352 | ||
415 | /* | 353 | /* |
@@ -417,22 +355,8 @@ static void xp_copy_rect(struct tridentfb_par *par, | |||
417 | */ | 355 | */ |
418 | static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp) | 356 | static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
419 | { | 357 | { |
420 | int tmp = 0; | 358 | int tmp = bpp == 24 ? 2: (bpp >> 4); |
421 | switch (bpp) { | 359 | |
422 | case 8: | ||
423 | tmp = 0; | ||
424 | break; | ||
425 | case 15: | ||
426 | tmp = 5; | ||
427 | break; | ||
428 | case 16: | ||
429 | tmp = 1; | ||
430 | break; | ||
431 | case 24: | ||
432 | case 32: | ||
433 | tmp = 2; | ||
434 | break; | ||
435 | } | ||
436 | writemmr(par, 0x2120, 0xF0000000); | 360 | writemmr(par, 0x2120, 0xF0000000); |
437 | writemmr(par, 0x2120, 0x40000000 | tmp); | 361 | writemmr(par, 0x2120, 0x40000000 | tmp); |
438 | writemmr(par, 0x2120, 0x80000000); | 362 | writemmr(par, 0x2120, 0x80000000); |
@@ -450,7 +374,8 @@ static void image_init_accel(struct tridentfb_par *par, int pitch, int bpp) | |||
450 | 374 | ||
451 | static void image_wait_engine(struct tridentfb_par *par) | 375 | static void image_wait_engine(struct tridentfb_par *par) |
452 | { | 376 | { |
453 | while (readmmr(par, 0x2164) & 0xF0000000) ; | 377 | while (readmmr(par, 0x2164) & 0xF0000000) |
378 | cpu_relax(); | ||
454 | } | 379 | } |
455 | 380 | ||
456 | static void image_fill_rect(struct tridentfb_par *par, | 381 | static void image_fill_rect(struct tridentfb_par *par, |
@@ -461,8 +386,8 @@ static void image_fill_rect(struct tridentfb_par *par, | |||
461 | 386 | ||
462 | writemmr(par, 0x2144, c); | 387 | writemmr(par, 0x2144, c); |
463 | 388 | ||
464 | writemmr(par, DR1, point(x, y)); | 389 | writemmr(par, DST1, point(x, y)); |
465 | writemmr(par, DR2, point(x + w - 1, y + h - 1)); | 390 | writemmr(par, DST2, point(x + w - 1, y + h - 1)); |
466 | 391 | ||
467 | writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9); | 392 | writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9); |
468 | } | 393 | } |
@@ -470,12 +395,11 @@ static void image_fill_rect(struct tridentfb_par *par, | |||
470 | static void image_copy_rect(struct tridentfb_par *par, | 395 | static void image_copy_rect(struct tridentfb_par *par, |
471 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) | 396 | u32 x1, u32 y1, u32 x2, u32 y2, u32 w, u32 h) |
472 | { | 397 | { |
473 | u32 s1, s2, d1, d2; | ||
474 | int direction = 2; | 398 | int direction = 2; |
475 | s1 = point(x1, y1); | 399 | u32 s1 = point(x1, y1); |
476 | s2 = point(x1 + w - 1, y1 + h - 1); | 400 | u32 s2 = point(x1 + w - 1, y1 + h - 1); |
477 | d1 = point(x2, y2); | 401 | u32 d1 = point(x2, y2); |
478 | d2 = point(x2 + w - 1, y2 + h - 1); | 402 | u32 d2 = point(x2 + w - 1, y2 + h - 1); |
479 | 403 | ||
480 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) | 404 | if ((y1 > y2) || ((y1 == y2) && (x1 > x2))) |
481 | direction = 0; | 405 | direction = 0; |
@@ -483,10 +407,10 @@ static void image_copy_rect(struct tridentfb_par *par, | |||
483 | writemmr(par, 0x2120, 0x80000000); | 407 | writemmr(par, 0x2120, 0x80000000); |
484 | writemmr(par, 0x2120, 0x90000000 | ROP_S); | 408 | writemmr(par, 0x2120, 0x90000000 | ROP_S); |
485 | 409 | ||
486 | writemmr(par, SR1, direction ? s2 : s1); | 410 | writemmr(par, SRC1, direction ? s2 : s1); |
487 | writemmr(par, SR2, direction ? s1 : s2); | 411 | writemmr(par, SRC2, direction ? s1 : s2); |
488 | writemmr(par, DR1, direction ? d2 : d1); | 412 | writemmr(par, DST1, direction ? d2 : d1); |
489 | writemmr(par, DR2, direction ? d1 : d2); | 413 | writemmr(par, DST2, direction ? d1 : d2); |
490 | writemmr(par, 0x2124, | 414 | writemmr(par, 0x2124, |
491 | 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction); | 415 | 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction); |
492 | } | 416 | } |
@@ -497,27 +421,12 @@ static void image_copy_rect(struct tridentfb_par *par, | |||
497 | 421 | ||
498 | static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp) | 422 | static void tgui_init_accel(struct tridentfb_par *par, int pitch, int bpp) |
499 | { | 423 | { |
500 | unsigned char x = 0; | 424 | unsigned char x = bpp == 24 ? 3 : (bpp >> 4); |
501 | 425 | ||
502 | /* disable clipping */ | 426 | /* disable clipping */ |
503 | writemmr(par, 0x2148, 0); | 427 | writemmr(par, 0x2148, 0); |
504 | writemmr(par, 0x214C, point(4095, 2047)); | 428 | writemmr(par, 0x214C, point(4095, 2047)); |
505 | 429 | ||
506 | switch (bpp) { | ||
507 | case 8: | ||
508 | x = 0; | ||
509 | break; | ||
510 | case 16: | ||
511 | x = 1; | ||
512 | break; | ||
513 | case 24: | ||
514 | x = 3; | ||
515 | break; | ||
516 | case 32: | ||
517 | x = 2; | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | switch ((pitch * bpp) / 8) { | 430 | switch ((pitch * bpp) / 8) { |
522 | case 8192: | 431 | case 8192: |
523 | case 512: | 432 | case 512: |
@@ -541,11 +450,11 @@ static void tgui_fill_rect(struct tridentfb_par *par, | |||
541 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) | 450 | u32 x, u32 y, u32 w, u32 h, u32 c, u32 rop) |
542 | { | 451 | { |
543 | t_outb(par, ROP_P, 0x2127); | 452 | t_outb(par, ROP_P, 0x2127); |
544 | writemmr(par, 0x212c, c); | 453 | writemmr(par, OLDCLR, c); |
545 | writemmr(par, 0x2128, 0x4020); | 454 | writemmr(par, DRAWFL, 0x4020); |
546 | writemmr(par, 0x2140, point(w - 1, h - 1)); | 455 | writemmr(par, OLDDIM, point(w - 1, h - 1)); |
547 | writemmr(par, 0x2138, point(x, y)); | 456 | writemmr(par, OLDDST, point(x, y)); |
548 | t_outb(par, 1, 0x2124); | 457 | t_outb(par, 1, OLDCMD); |
549 | } | 458 | } |
550 | 459 | ||
551 | static void tgui_copy_rect(struct tridentfb_par *par, | 460 | static void tgui_copy_rect(struct tridentfb_par *par, |
@@ -572,12 +481,12 @@ static void tgui_copy_rect(struct tridentfb_par *par, | |||
572 | y2_tmp = y2; | 481 | y2_tmp = y2; |
573 | } | 482 | } |
574 | 483 | ||
575 | writemmr(par, 0x2128, 0x4 | flags); | 484 | writemmr(par, DRAWFL, 0x4 | flags); |
576 | t_outb(par, ROP_S, 0x2127); | 485 | t_outb(par, ROP_S, 0x2127); |
577 | writemmr(par, 0x213C, point(x1_tmp, y1_tmp)); | 486 | writemmr(par, OLDSRC, point(x1_tmp, y1_tmp)); |
578 | writemmr(par, 0x2138, point(x2_tmp, y2_tmp)); | 487 | writemmr(par, OLDDST, point(x2_tmp, y2_tmp)); |
579 | writemmr(par, 0x2140, point(w - 1, h - 1)); | 488 | writemmr(par, OLDDIM, point(w - 1, h - 1)); |
580 | t_outb(par, 1, 0x2124); | 489 | t_outb(par, 1, OLDCMD); |
581 | } | 490 | } |
582 | 491 | ||
583 | /* | 492 | /* |
@@ -588,37 +497,40 @@ static void tridentfb_fillrect(struct fb_info *info, | |||
588 | const struct fb_fillrect *fr) | 497 | const struct fb_fillrect *fr) |
589 | { | 498 | { |
590 | struct tridentfb_par *par = info->par; | 499 | struct tridentfb_par *par = info->par; |
591 | int bpp = info->var.bits_per_pixel; | 500 | int col; |
592 | int col = 0; | ||
593 | 501 | ||
594 | switch (bpp) { | 502 | if (info->var.bits_per_pixel == 8) { |
595 | default: | 503 | col = fr->color; |
596 | case 8: | ||
597 | col |= fr->color; | ||
598 | col |= col << 8; | 504 | col |= col << 8; |
599 | col |= col << 16; | 505 | col |= col << 16; |
600 | break; | 506 | } else |
601 | case 16: | ||
602 | col = ((u32 *)(info->pseudo_palette))[fr->color]; | ||
603 | break; | ||
604 | case 32: | ||
605 | col = ((u32 *)(info->pseudo_palette))[fr->color]; | 507 | col = ((u32 *)(info->pseudo_palette))[fr->color]; |
606 | break; | ||
607 | } | ||
608 | 508 | ||
509 | par->wait_engine(par); | ||
609 | par->fill_rect(par, fr->dx, fr->dy, fr->width, | 510 | par->fill_rect(par, fr->dx, fr->dy, fr->width, |
610 | fr->height, col, fr->rop); | 511 | fr->height, col, fr->rop); |
611 | par->wait_engine(par); | ||
612 | } | 512 | } |
513 | |||
613 | static void tridentfb_copyarea(struct fb_info *info, | 514 | static void tridentfb_copyarea(struct fb_info *info, |
614 | const struct fb_copyarea *ca) | 515 | const struct fb_copyarea *ca) |
615 | { | 516 | { |
616 | struct tridentfb_par *par = info->par; | 517 | struct tridentfb_par *par = info->par; |
617 | 518 | ||
519 | par->wait_engine(par); | ||
618 | par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy, | 520 | par->copy_rect(par, ca->sx, ca->sy, ca->dx, ca->dy, |
619 | ca->width, ca->height); | 521 | ca->width, ca->height); |
522 | } | ||
523 | |||
524 | static int tridentfb_sync(struct fb_info *info) | ||
525 | { | ||
526 | struct tridentfb_par *par = info->par; | ||
527 | |||
620 | par->wait_engine(par); | 528 | par->wait_engine(par); |
529 | return 0; | ||
621 | } | 530 | } |
531 | #else | ||
532 | #define tridentfb_fillrect cfb_fillrect | ||
533 | #define tridentfb_copyarea cfb_copyarea | ||
622 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ | 534 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ |
623 | 535 | ||
624 | /* | 536 | /* |
@@ -921,6 +833,8 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var, | |||
921 | /* check color depth */ | 833 | /* check color depth */ |
922 | if (bpp == 24) | 834 | if (bpp == 24) |
923 | bpp = var->bits_per_pixel = 32; | 835 | bpp = var->bits_per_pixel = 32; |
836 | if (bpp != 8 && bpp != 16 && bpp != 32) | ||
837 | return -EINVAL; | ||
924 | if (par->chip_id == TGUI9440 && bpp == 32) | 838 | if (par->chip_id == TGUI9440 && bpp == 32) |
925 | return -EINVAL; | 839 | return -EINVAL; |
926 | /* check whether resolution fits on panel and in memory */ | 840 | /* check whether resolution fits on panel and in memory */ |
@@ -928,8 +842,15 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var, | |||
928 | return -EINVAL; | 842 | return -EINVAL; |
929 | /* various resolution checks */ | 843 | /* various resolution checks */ |
930 | var->xres = (var->xres + 7) & ~0x7; | 844 | var->xres = (var->xres + 7) & ~0x7; |
931 | if (var->xres != var->xres_virtual) | 845 | if (var->xres > var->xres_virtual) |
932 | var->xres_virtual = var->xres; | 846 | var->xres_virtual = var->xres; |
847 | if (var->yres > var->yres_virtual) | ||
848 | var->yres_virtual = var->yres; | ||
849 | if (var->xres_virtual > 4095 || var->yres > 2048) | ||
850 | return -EINVAL; | ||
851 | /* prevent from position overflow for acceleration */ | ||
852 | if (var->yres_virtual > 0xffff) | ||
853 | return -EINVAL; | ||
933 | line_length = var->xres_virtual * bpp / 8; | 854 | line_length = var->xres_virtual * bpp / 8; |
934 | #ifdef CONFIG_FB_TRIDENT_ACCEL | 855 | #ifdef CONFIG_FB_TRIDENT_ACCEL |
935 | if (!is3Dchip(par->chip_id)) { | 856 | if (!is3Dchip(par->chip_id)) { |
@@ -944,6 +865,8 @@ static int tridentfb_check_var(struct fb_var_screeninfo *var, | |||
944 | var->xres_virtual = 4096 * 8 / bpp; | 865 | var->xres_virtual = 4096 * 8 / bpp; |
945 | else if (line_length <= 8192) | 866 | else if (line_length <= 8192) |
946 | var->xres_virtual = 8192 * 8 / bpp; | 867 | var->xres_virtual = 8192 * 8 / bpp; |
868 | else | ||
869 | return -EINVAL; | ||
947 | 870 | ||
948 | line_length = var->xres_virtual * bpp / 8; | 871 | line_length = var->xres_virtual * bpp / 8; |
949 | } | 872 | } |
@@ -1229,9 +1152,6 @@ static int tridentfb_set_par(struct fb_info *info) | |||
1229 | case 8: | 1152 | case 8: |
1230 | tmp = 0; | 1153 | tmp = 0; |
1231 | break; | 1154 | break; |
1232 | case 15: | ||
1233 | tmp = 0x10; | ||
1234 | break; | ||
1235 | case 16: | 1155 | case 16: |
1236 | tmp = 0x30; | 1156 | tmp = 0x30; |
1237 | break; | 1157 | break; |
@@ -1352,10 +1272,11 @@ static struct fb_ops tridentfb_ops = { | |||
1352 | .fb_blank = tridentfb_blank, | 1272 | .fb_blank = tridentfb_blank, |
1353 | .fb_check_var = tridentfb_check_var, | 1273 | .fb_check_var = tridentfb_check_var, |
1354 | .fb_set_par = tridentfb_set_par, | 1274 | .fb_set_par = tridentfb_set_par, |
1355 | #ifdef CONFIG_FB_TRIDENT_ACCEL | ||
1356 | .fb_fillrect = tridentfb_fillrect, | 1275 | .fb_fillrect = tridentfb_fillrect, |
1357 | .fb_copyarea = tridentfb_copyarea, | 1276 | .fb_copyarea = tridentfb_copyarea, |
1358 | .fb_imageblit = cfb_imageblit, | 1277 | .fb_imageblit = cfb_imageblit, |
1278 | #ifdef CONFIG_FB_TRIDENT_ACCEL | ||
1279 | .fb_sync = tridentfb_sync, | ||
1359 | #endif | 1280 | #endif |
1360 | }; | 1281 | }; |
1361 | 1282 | ||
@@ -1366,7 +1287,6 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1366 | unsigned char revision; | 1287 | unsigned char revision; |
1367 | struct fb_info *info; | 1288 | struct fb_info *info; |
1368 | struct tridentfb_par *default_par; | 1289 | struct tridentfb_par *default_par; |
1369 | int defaultaccel; | ||
1370 | int chip3D; | 1290 | int chip3D; |
1371 | int chip_id; | 1291 | int chip_id; |
1372 | 1292 | ||
@@ -1448,9 +1368,6 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1448 | 1368 | ||
1449 | default_par->chip_id = chip_id; | 1369 | default_par->chip_id = chip_id; |
1450 | 1370 | ||
1451 | /* acceleration is on by default for 3D chips */ | ||
1452 | defaultaccel = chip3D && !noaccel; | ||
1453 | |||
1454 | /* setup MMIO region */ | 1371 | /* setup MMIO region */ |
1455 | tridentfb_fix.mmio_start = pci_resource_start(dev, 1); | 1372 | tridentfb_fix.mmio_start = pci_resource_start(dev, 1); |
1456 | tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000; | 1373 | tridentfb_fix.mmio_len = chip3D ? 0x20000 : 0x10000; |
@@ -1515,7 +1432,7 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1515 | if (err < 0) | 1432 | if (err < 0) |
1516 | goto out_unmap2; | 1433 | goto out_unmap2; |
1517 | 1434 | ||
1518 | if (defaultaccel && default_par->init_accel) | 1435 | if (!noaccel && default_par->init_accel) |
1519 | info->var.accel_flags |= FB_ACCELF_TEXT; | 1436 | info->var.accel_flags |= FB_ACCELF_TEXT; |
1520 | else | 1437 | else |
1521 | info->var.accel_flags &= ~FB_ACCELF_TEXT; | 1438 | info->var.accel_flags &= ~FB_ACCELF_TEXT; |