diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2007-10-16 04:28:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:16 -0400 |
commit | 1d677a6dfaac1d1cf51a7f58847077240985faf2 (patch) | |
tree | ba349d67ae9c91f5499f44c5f59d326e64975c23 /drivers/video | |
parent | 8f5d050af1da13455068cefbaf3c1bc306d6fe0b (diff) |
pm3fb: hardware cursor support
This patch adds hardware cursor support to the pm3fb driver.
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')
-rw-r--r-- | drivers/video/pm3fb.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 1c41a4e5bc99..6a64b934133a 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
@@ -55,6 +55,7 @@ | |||
55 | /* | 55 | /* |
56 | * Driver data | 56 | * Driver data |
57 | */ | 57 | */ |
58 | static int hwcursor = 1; | ||
58 | static char *mode_option __devinitdata; | 59 | static char *mode_option __devinitdata; |
59 | static int noaccel __devinitdata; | 60 | static int noaccel __devinitdata; |
60 | 61 | ||
@@ -604,6 +605,117 @@ static void pm3fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
604 | } | 605 | } |
605 | /* end of acceleration functions */ | 606 | /* end of acceleration functions */ |
606 | 607 | ||
608 | /* | ||
609 | * Hardware Cursor support. | ||
610 | */ | ||
611 | static const u8 cursor_bits_lookup[16] = { | ||
612 | 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, | ||
613 | 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 | ||
614 | }; | ||
615 | |||
616 | static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
617 | { | ||
618 | struct pm3_par *par = info->par; | ||
619 | u8 mode; | ||
620 | |||
621 | if (!hwcursor) | ||
622 | return -EINVAL; /* just to force soft_cursor() call */ | ||
623 | |||
624 | /* Too large of a cursor or wrong bpp :-( */ | ||
625 | if (cursor->image.width > 64 || | ||
626 | cursor->image.height > 64 || | ||
627 | cursor->image.depth > 1) | ||
628 | return -EINVAL; | ||
629 | |||
630 | mode = PM3RD_CursorMode_TYPE_X; | ||
631 | if (cursor->enable) | ||
632 | mode |= PM3RD_CursorMode_CURSOR_ENABLE; | ||
633 | |||
634 | PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode); | ||
635 | |||
636 | /* | ||
637 | * If the cursor is not be changed this means either we want the | ||
638 | * current cursor state (if enable is set) or we want to query what | ||
639 | * we can do with the cursor (if enable is not set) | ||
640 | */ | ||
641 | if (!cursor->set) | ||
642 | return 0; | ||
643 | |||
644 | if (cursor->set & FB_CUR_SETPOS) { | ||
645 | int x = cursor->image.dx - info->var.xoffset; | ||
646 | int y = cursor->image.dy - info->var.yoffset; | ||
647 | |||
648 | PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff); | ||
649 | PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf); | ||
650 | PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff); | ||
651 | PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf); | ||
652 | } | ||
653 | |||
654 | if (cursor->set & FB_CUR_SETHOT) { | ||
655 | PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX, | ||
656 | cursor->hot.x & 0x3f); | ||
657 | PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY, | ||
658 | cursor->hot.y & 0x3f); | ||
659 | } | ||
660 | |||
661 | if (cursor->set & FB_CUR_SETCMAP) { | ||
662 | u32 fg_idx = cursor->image.fg_color; | ||
663 | u32 bg_idx = cursor->image.bg_color; | ||
664 | struct fb_cmap cmap = info->cmap; | ||
665 | |||
666 | /* the X11 driver says one should use these color registers */ | ||
667 | PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39), | ||
668 | cmap.red[fg_idx] >> 8 ); | ||
669 | PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40), | ||
670 | cmap.green[fg_idx] >> 8 ); | ||
671 | PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41), | ||
672 | cmap.blue[fg_idx] >> 8 ); | ||
673 | |||
674 | PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42), | ||
675 | cmap.red[bg_idx] >> 8 ); | ||
676 | PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43), | ||
677 | cmap.green[bg_idx] >> 8 ); | ||
678 | PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44), | ||
679 | cmap.blue[bg_idx] >> 8 ); | ||
680 | } | ||
681 | |||
682 | if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { | ||
683 | u8 *bitmap = (u8 *)cursor->image.data; | ||
684 | u8 *mask = (u8 *)cursor->mask; | ||
685 | int i; | ||
686 | int pos = PM3RD_CursorPattern(0); | ||
687 | |||
688 | for (i = 0; i < cursor->image.height; i++) { | ||
689 | int j = (cursor->image.width + 7) >> 3; | ||
690 | int k = 8 - j; | ||
691 | |||
692 | for (; j > 0; j--) { | ||
693 | u8 data = *bitmap ^ *mask; | ||
694 | |||
695 | if (cursor->rop == ROP_COPY) | ||
696 | data = *mask & *bitmap; | ||
697 | /* Upper 4 bits of bitmap data */ | ||
698 | PM3_WRITE_DAC_REG(par, pos++, | ||
699 | cursor_bits_lookup[data >> 4] | | ||
700 | (cursor_bits_lookup[*mask >> 4] << 1)); | ||
701 | /* Lower 4 bits of bitmap */ | ||
702 | PM3_WRITE_DAC_REG(par, pos++, | ||
703 | cursor_bits_lookup[data & 0xf] | | ||
704 | (cursor_bits_lookup[*mask & 0xf] << 1)); | ||
705 | bitmap++; | ||
706 | mask++; | ||
707 | } | ||
708 | for (; k > 0; k--) { | ||
709 | PM3_WRITE_DAC_REG(par, pos++, 0); | ||
710 | PM3_WRITE_DAC_REG(par, pos++, 0); | ||
711 | } | ||
712 | } | ||
713 | while (pos < PM3RD_CursorPattern(1024)) | ||
714 | PM3_WRITE_DAC_REG(par, pos++, 0); | ||
715 | } | ||
716 | return 0; | ||
717 | } | ||
718 | |||
607 | /* write the mode to registers */ | 719 | /* write the mode to registers */ |
608 | static void pm3fb_write_mode(struct fb_info *info) | 720 | static void pm3fb_write_mode(struct fb_info *info) |
609 | { | 721 | { |
@@ -1103,6 +1215,7 @@ static struct fb_ops pm3fb_ops = { | |||
1103 | .fb_imageblit = pm3fb_imageblit, | 1215 | .fb_imageblit = pm3fb_imageblit, |
1104 | .fb_blank = pm3fb_blank, | 1216 | .fb_blank = pm3fb_blank, |
1105 | .fb_sync = pm3fb_sync, | 1217 | .fb_sync = pm3fb_sync, |
1218 | .fb_cursor = pm3fb_cursor, | ||
1106 | }; | 1219 | }; |
1107 | 1220 | ||
1108 | /* ------------------------------------------------------------------------- */ | 1221 | /* ------------------------------------------------------------------------- */ |
@@ -1418,6 +1531,8 @@ static int __init pm3fb_setup(char *options) | |||
1418 | continue; | 1531 | continue; |
1419 | else if (!strncmp(this_opt, "noaccel", 7)) | 1532 | else if (!strncmp(this_opt, "noaccel", 7)) |
1420 | noaccel = 1; | 1533 | noaccel = 1; |
1534 | else if (!strncmp(this_opt, "hwcursor=", 9)) | ||
1535 | hwcursor = simple_strtoul(this_opt + 9, NULL, 0); | ||
1421 | #ifdef CONFIG_MTRR | 1536 | #ifdef CONFIG_MTRR |
1422 | else if (!strncmp(this_opt, "nomtrr", 6)) | 1537 | else if (!strncmp(this_opt, "nomtrr", 6)) |
1423 | nomtrr = 1; | 1538 | nomtrr = 1; |
@@ -1457,6 +1572,9 @@ module_init(pm3fb_init); | |||
1457 | 1572 | ||
1458 | module_param(noaccel, bool, 0); | 1573 | module_param(noaccel, bool, 0); |
1459 | MODULE_PARM_DESC(noaccel, "Disable acceleration"); | 1574 | MODULE_PARM_DESC(noaccel, "Disable acceleration"); |
1575 | module_param(hwcursor, int, 0644); | ||
1576 | MODULE_PARM_DESC(hwcursor, "Enable hardware cursor " | ||
1577 | "(1=enable, 0=disable, default=1)"); | ||
1460 | #ifdef CONFIG_MTRR | 1578 | #ifdef CONFIG_MTRR |
1461 | module_param(nomtrr, bool, 0); | 1579 | module_param(nomtrr, bool, 0); |
1462 | MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); | 1580 | MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); |