aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pm3fb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2007-10-16 04:28:29 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:14 -0400
commite7f76df9648ccd69a99fe6bc7d774dc05922f2f0 (patch)
tree6ec2d9ad3aeef81b0a89f2eb8f8c63414582d8db /drivers/video/pm3fb.c
parent0a0b53f66043b4f4da728b391232de5e5d22f145 (diff)
pm3fb: copyarea and partial imageblit suppor
This patch adds accelerated copyarea and partially accelerated imageblit functions. There is also fixed one register address in the pm3fb.h file. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Antonino Daplas <adaplas@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/pm3fb.c')
-rw-r--r--drivers/video/pm3fb.c180
1 files changed, 169 insertions, 11 deletions
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 5b3f54c0918e..438872a5f43f 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -276,15 +276,22 @@ static void pm3fb_init_engine(struct fb_info *info)
276 276
277 PM3_WAIT(par, 2); 277 PM3_WAIT(par, 2);
278 { 278 {
279 unsigned long rm = 1; 279 /* invert bits in bitmask */
280 unsigned long rm = 1 | (3 << 7);
280 switch (info->var.bits_per_pixel) { 281 switch (info->var.bits_per_pixel) {
281 case 8: 282 case 8:
282 PM3_WRITE_REG(par, PM3PixelSize, 283 PM3_WRITE_REG(par, PM3PixelSize,
283 PM3PixelSize_GLOBAL_8BIT); 284 PM3PixelSize_GLOBAL_8BIT);
285#ifdef __BIG_ENDIAN
286 rm |= 3 << 15;
287#endif
284 break; 288 break;
285 case 16: 289 case 16:
286 PM3_WRITE_REG(par, PM3PixelSize, 290 PM3_WRITE_REG(par, PM3PixelSize,
287 PM3PixelSize_GLOBAL_16BIT); 291 PM3PixelSize_GLOBAL_16BIT);
292#ifdef __BIG_ENDIAN
293 rm |= 2 << 15;
294#endif
288 break; 295 break;
289 case 32: 296 case 32:
290 PM3_WRITE_REG(par, PM3PixelSize, 297 PM3_WRITE_REG(par, PM3PixelSize,
@@ -394,18 +401,18 @@ static void pm3fb_fillrect (struct fb_info *info,
394 color |= color << 16; 401 color |= color << 16;
395 402
396 PM3_WAIT(par, 4); 403 PM3_WAIT(par, 4);
397 404 /* ROP Ox3 is GXcopy */
398 PM3_WRITE_REG(par, PM3Config2D, 405 PM3_WRITE_REG(par, PM3Config2D,
399 PM3Config2D_UseConstantSource | 406 PM3Config2D_UseConstantSource |
400 PM3Config2D_ForegroundROPEnable | 407 PM3Config2D_ForegroundROPEnable |
401 (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */ 408 (PM3Config2D_ForegroundROP(0x3)) |
402 PM3Config2D_FBWriteEnable); 409 PM3Config2D_FBWriteEnable);
403 410
404 PM3_WRITE_REG(par, PM3ForegroundColor, color); 411 PM3_WRITE_REG(par, PM3ForegroundColor, color);
405 412
406 PM3_WRITE_REG(par, PM3RectanglePosition, 413 PM3_WRITE_REG(par, PM3RectanglePosition,
407 (PM3RectanglePosition_XOffset(modded.dx)) | 414 (PM3RectanglePosition_XOffset(modded.dx)) |
408 (PM3RectanglePosition_YOffset(modded.dy))); 415 (PM3RectanglePosition_YOffset(modded.dy)));
409 416
410 PM3_WRITE_REG(par, PM3Render2D, 417 PM3_WRITE_REG(par, PM3Render2D,
411 PM3Render2D_XPositive | 418 PM3Render2D_XPositive |
@@ -415,6 +422,154 @@ static void pm3fb_fillrect (struct fb_info *info,
415 (PM3Render2D_Width(modded.width)) | 422 (PM3Render2D_Width(modded.width)) |
416 (PM3Render2D_Height(modded.height))); 423 (PM3Render2D_Height(modded.height)));
417} 424}
425
426static void pm3fb_copyarea(struct fb_info *info,
427 const struct fb_copyarea *area)
428{
429 struct pm3_par *par = info->par;
430 struct fb_copyarea modded;
431 u32 vxres, vyres;
432 int x_align, o_x, o_y;
433
434 if (info->state != FBINFO_STATE_RUNNING)
435 return;
436 if (info->flags & FBINFO_HWACCEL_DISABLED) {
437 cfb_copyarea(info, area);
438 return;
439 }
440
441 memcpy(&modded, area, sizeof(struct fb_copyarea));
442
443 vxres = info->var.xres_virtual;
444 vyres = info->var.yres_virtual;
445
446 if(!modded.width || !modded.height ||
447 modded.sx >= vxres || modded.sy >= vyres ||
448 modded.dx >= vxres || modded.dy >= vyres)
449 return;
450
451 if(modded.sx + modded.width > vxres)
452 modded.width = vxres - modded.sx;
453 if(modded.dx + modded.width > vxres)
454 modded.width = vxres - modded.dx;
455 if(modded.sy + modded.height > vyres)
456 modded.height = vyres - modded.sy;
457 if(modded.dy + modded.height > vyres)
458 modded.height = vyres - modded.dy;
459
460 o_x = modded.sx - modded.dx; /*(sx > dx ) ? (sx - dx) : (dx - sx); */
461 o_y = modded.sy - modded.dy; /*(sy > dy ) ? (sy - dy) : (dy - sy); */
462
463 x_align = (modded.sx & 0x1f);
464
465 PM3_WAIT(par, 6);
466
467 PM3_WRITE_REG(par, PM3Config2D,
468 PM3Config2D_UserScissorEnable |
469 PM3Config2D_ForegroundROPEnable |
470 PM3Config2D_Blocking |
471 (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
472 PM3Config2D_FBWriteEnable);
473
474 PM3_WRITE_REG(par, PM3ScissorMinXY,
475 ((modded.dy & 0x0fff) << 16) | (modded.dx & 0x0fff));
476 PM3_WRITE_REG(par, PM3ScissorMaxXY,
477 (((modded.dy + modded.height) & 0x0fff) << 16) |
478 ((modded.dx + modded.width) & 0x0fff));
479
480 PM3_WRITE_REG(par, PM3FBSourceReadBufferOffset,
481 PM3FBSourceReadBufferOffset_XOffset(o_x) |
482 PM3FBSourceReadBufferOffset_YOffset(o_y));
483
484 PM3_WRITE_REG(par, PM3RectanglePosition,
485 (PM3RectanglePosition_XOffset(modded.dx - x_align)) |
486 (PM3RectanglePosition_YOffset(modded.dy)));
487
488 PM3_WRITE_REG(par, PM3Render2D,
489 ((modded.sx > modded.dx) ? PM3Render2D_XPositive : 0) |
490 ((modded.sy > modded.dy) ? PM3Render2D_YPositive : 0) |
491 PM3Render2D_Operation_Normal |
492 PM3Render2D_SpanOperation |
493 PM3Render2D_FBSourceReadEnable |
494 (PM3Render2D_Width(modded.width + x_align)) |
495 (PM3Render2D_Height(modded.height)));
496}
497
498static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image)
499{
500 struct pm3_par *par = info->par;
501 u32 height = image->height;
502 u32 fgx, bgx;
503 const u32 *src = (const u32*)image->data;
504
505 switch (info->fix.visual) {
506 case FB_VISUAL_PSEUDOCOLOR:
507 fgx = image->fg_color;
508 bgx = image->bg_color;
509 break;
510 case FB_VISUAL_TRUECOLOR:
511 default:
512 fgx = par->palette[image->fg_color];
513 bgx = par->palette[image->bg_color];
514 break;
515 }
516 if (image->depth != 1 || (image->width & 0x1f)) {
517 return cfb_imageblit(info, image);
518 }
519 if (info->var.bits_per_pixel == 8) {
520 fgx |= fgx << 8;
521 bgx |= bgx << 8;
522 }
523 if (info->var.bits_per_pixel <= 16) {
524 fgx |= fgx << 16;
525 bgx |= bgx << 16;
526 }
527
528 PM3_WAIT(par, 5);
529
530 PM3_WRITE_REG(par, PM3ForegroundColor, fgx);
531 PM3_WRITE_REG(par, PM3BackgroundColor, bgx);
532
533 /* ROP Ox3 is GXcopy */
534 PM3_WRITE_REG(par, PM3Config2D,
535 PM3Config2D_UseConstantSource |
536 PM3Config2D_ForegroundROPEnable |
537 (PM3Config2D_ForegroundROP(0x3)) |
538 PM3Config2D_OpaqueSpan |
539 PM3Config2D_FBWriteEnable);
540 PM3_WRITE_REG(par, PM3RectanglePosition,
541 (PM3RectanglePosition_XOffset(image->dx)) |
542 (PM3RectanglePosition_YOffset(image->dy)));
543 PM3_WRITE_REG(par, PM3Render2D,
544 PM3Render2D_XPositive |
545 PM3Render2D_YPositive |
546 PM3Render2D_Operation_SyncOnBitMask |
547 PM3Render2D_SpanOperation |
548 (PM3Render2D_Width(image->width)) |
549 (PM3Render2D_Height(image->height)));
550
551
552 while (height--) {
553 u32 width = (image->width + 31) >> 5;
554
555 while (width >= PM3_FIFO_SIZE) {
556 int i = PM3_FIFO_SIZE - 1;
557
558 PM3_WAIT(par, PM3_FIFO_SIZE);
559 while (i--) {
560 PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
561 src++;
562 }
563 width -= PM3_FIFO_SIZE - 1;
564 }
565
566 PM3_WAIT(par, width + 1);
567 while (width--) {
568 PM3_WRITE_REG(par, PM3BitMaskPattern, *src);
569 src++;
570 }
571 }
572}
418/* end of acceleration functions */ 573/* end of acceleration functions */
419 574
420/* write the mode to registers */ 575/* write the mode to registers */
@@ -907,8 +1062,8 @@ static struct fb_ops pm3fb_ops = {
907 .fb_setcolreg = pm3fb_setcolreg, 1062 .fb_setcolreg = pm3fb_setcolreg,
908 .fb_pan_display = pm3fb_pan_display, 1063 .fb_pan_display = pm3fb_pan_display,
909 .fb_fillrect = pm3fb_fillrect, 1064 .fb_fillrect = pm3fb_fillrect,
910 .fb_copyarea = cfb_copyarea, 1065 .fb_copyarea = pm3fb_copyarea,
911 .fb_imageblit = cfb_imageblit, 1066 .fb_imageblit = pm3fb_imageblit,
912 .fb_blank = pm3fb_blank, 1067 .fb_blank = pm3fb_blank,
913 .fb_sync = pm3fb_sync, 1068 .fb_sync = pm3fb_sync,
914}; 1069};
@@ -1080,7 +1235,10 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
1080 info->fix = pm3fb_fix; 1235 info->fix = pm3fb_fix;
1081 info->pseudo_palette = par->palette; 1236 info->pseudo_palette = par->palette;
1082 info->flags = FBINFO_DEFAULT | 1237 info->flags = FBINFO_DEFAULT |
1083 FBINFO_HWACCEL_FILLRECT;/* | FBINFO_HWACCEL_YPAN;*/ 1238/* FBINFO_HWACCEL_YPAN |*/
1239 FBINFO_HWACCEL_COPYAREA |
1240 FBINFO_HWACCEL_IMAGEBLIT |
1241 FBINFO_HWACCEL_FILLRECT;
1084 1242
1085 /* 1243 /*
1086 * This should give a reasonable default video mode. The following is 1244 * This should give a reasonable default video mode. The following is