aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/pm3fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/pm3fb.c')
-rw-r--r--drivers/video/pm3fb.c118
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 */
58static int hwcursor = 1;
58static char *mode_option __devinitdata; 59static char *mode_option __devinitdata;
59static int noaccel __devinitdata; 60static 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 */
611static 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
616static 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 */
608static void pm3fb_write_mode(struct fb_info *info) 720static 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
1458module_param(noaccel, bool, 0); 1573module_param(noaccel, bool, 0);
1459MODULE_PARM_DESC(noaccel, "Disable acceleration"); 1574MODULE_PARM_DESC(noaccel, "Disable acceleration");
1575module_param(hwcursor, int, 0644);
1576MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
1577 "(1=enable, 0=disable, default=1)");
1460#ifdef CONFIG_MTRR 1578#ifdef CONFIG_MTRR
1461module_param(nomtrr, bool, 0); 1579module_param(nomtrr, bool, 0);
1462MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)"); 1580MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");