From: "Antonino A. Daplas" <adaplas@gmail.com>
To: Andrew Morton <akpm@osdl.org>
Cc: Linux Fbdev development list <linux-fbdev-devel@lists.sourceforge.net>
Subject: [PATCH 08/11] tdfxfb: hardware cursor
Date: Wed, 01 Aug 2007 15:48:23 +0800 [thread overview]
Message-ID: <46B03AC7.10505@gmail.com> (raw)
From: Krzysztof Helt <krzysztof.h1@wp.pl>
This patch adds hardware cursor support to the tdfxfb driver.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
---
drivers/video/tdfxfb.c | 169 +++++++++++++++++++++---------------------------
include/video/tdfx.h | 8 --
2 files changed, 74 insertions(+), 103 deletions(-)
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 7d0c50e..c5ba647 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -67,7 +67,6 @@ #include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
-#include <linux/timer.h>
#include <linux/spinlock.h>
#include <video/tdfx.h>
@@ -148,8 +147,9 @@ MODULE_DEVICE_TABLE(pci, tdfxfb_id_table
/*
* Driver data
*/
-static int nopan = 0;
-static int nowrap = 1; // not implemented (yet)
+static int nopan;
+static int nowrap = 1; /* not implemented (yet) */
+static int hwcursor = 1;
static char *mode_option __devinitdata = NULL;
/* -------------------------------------------------------------------------
@@ -378,7 +378,7 @@ #endif
tdfx_outl(par, VGAINIT0, reg->vgainit0);
tdfx_outl(par, DACMODE, reg->dacmode);
tdfx_outl(par, VIDDESKSTRIDE, reg->stride);
- tdfx_outl(par, HWCURPATADDR, 0);
+ tdfx_outl(par, HWCURPATADDR, reg->curspataddr);
tdfx_outl(par, VIDSCREENSIZE, reg->screensize);
tdfx_outl(par, VIDDESKSTART, reg->startaddr);
@@ -453,6 +453,7 @@ static int tdfxfb_check_var(struct fb_va
DPRINTK("xoffset not supported\n");
return -EINVAL;
}
+ var->yoffset = 0;
/* Banshee doesn't support interlace, but Voodoo4/5 and probably Voodoo3 do. */
/* no direct information about device id now? use max_pixclock for this... */
@@ -663,6 +664,9 @@ static int tdfxfb_set_par(struct fb_info
VGAINIT0_EXTSHIFTOUT;
reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff;
+ if (hwcursor)
+ reg.curspataddr = info->fix.smem_len;
+
reg.cursloc = 0;
reg.cursc0 = 0;
@@ -1012,11 +1016,25 @@ #endif
}
#endif /* CONFIG_FB_3DFX_ACCEL */
-#ifdef TDFX_HARDWARE_CURSOR
static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct tdfx_par *par = info->par;
- unsigned long flags;
+ u32 vidcfg;
+
+ if (!hwcursor)
+ return -EINVAL; /* just to force soft_cursor() call */
+
+ /* Too large of a cursor or wrong bpp :-( */
+ if (cursor->image.width > 64 ||
+ cursor->image.height > 64 ||
+ cursor->image.depth > 1)
+ return -EINVAL;
+
+ vidcfg = tdfx_inl(par, VIDPROCCFG);
+ if (cursor->enable)
+ tdfx_outl(par, VIDPROCCFG, vidcfg | VIDCFG_HWCURSOR_ENABLE);
+ else
+ tdfx_outl(par, VIDPROCCFG, vidcfg & ~VIDCFG_HWCURSOR_ENABLE);
/*
* If the cursor is not be changed this means either we want the
@@ -1026,69 +1044,34 @@ static int tdfxfb_cursor(struct fb_info
if (!cursor->set)
return 0;
- /* Too large of a cursor :-( */
- if (cursor->image.width > 64 || cursor->image.height > 64)
- return -ENXIO;
-
- /*
- * If we are going to be changing things we should disable
- * the cursor first
- */
- if (info->cursor.enable) {
- spin_lock_irqsave(&par->DAClock, flags);
- info->cursor.enable = 0;
- del_timer(&(par->hwcursor.timer));
- tdfx_outl(par, VIDPROCCFG, par->hwcursor.disable);
- spin_unlock_irqrestore(&par->DAClock, flags);
- }
-
- /* Disable the Cursor */
- if ((cursor->set && FB_CUR_SETCUR) && !cursor->enable)
- return 0;
-
/* fix cursor color - XFree86 forgets to restore it properly */
- if (cursor->set && FB_CUR_SETCMAP) {
- struct fb_cmap cmap = cursor->image.cmap;
+ if (cursor->set & FB_CUR_SETCMAP) {
+ struct fb_cmap cmap = info->cmap;
+ u32 bg_idx = cursor->image.bg_color;
+ u32 fg_idx = cursor->image.fg_color;
unsigned long bg_color, fg_color;
- cmap.len = 2; /* Voodoo 3+ only support 2 color cursors */
- fg_color = ((cmap.red[cmap.start] << 16) |
- (cmap.green[cmap.start] << 8) |
- (cmap.blue[cmap.start]));
- bg_color = ((cmap.red[cmap.start + 1] << 16) |
- (cmap.green[cmap.start + 1] << 8) |
- (cmap.blue[cmap.start + 1]));
- fb_copy_cmap(&cmap, &info->cursor.image.cmap);
- spin_lock_irqsave(&par->DAClock, flags);
+ fg_color = (((u32)cmap.red[fg_idx] & 0xff00) << 8) |
+ (((u32)cmap.green[fg_idx] & 0xff00) << 0) |
+ (((u32)cmap.blue[fg_idx] & 0xff00) >> 8);
+ bg_color = (((u32)cmap.red[bg_idx] & 0xff00) << 8) |
+ (((u32)cmap.green[bg_idx] & 0xff00) << 0) |
+ (((u32)cmap.blue[bg_idx] & 0xff00) >> 8);
banshee_make_room(par, 2);
tdfx_outl(par, HWCURC0, bg_color);
tdfx_outl(par, HWCURC1, fg_color);
- spin_unlock_irqrestore(&par->DAClock, flags);
}
- if (cursor->set && FB_CUR_SETPOS) {
- int x, y;
+ if (cursor->set & FB_CUR_SETPOS) {
+ int x = cursor->image.dx;
+ int y = cursor->image.dy - info->var.yoffset;
- x = cursor->image.dx;
- y = cursor->image.dy;
- y -= info->var.yoffset;
- info->cursor.image.dx = x;
- info->cursor.image.dy = y;
x += 63;
y += 63;
- spin_lock_irqsave(&par->DAClock, flags);
banshee_make_room(par, 1);
tdfx_outl(par, HWCURLOC, (y << 16) + x);
- spin_unlock_irqrestore(&par->DAClock, flags);
}
-
- /* Not supported so we fake it */
- if (cursor->set && FB_CUR_SETHOT) {
- info->cursor.hot.x = cursor->hot.x;
- info->cursor.hot.y = cursor->hot.y;
- }
-
- if (cursor->set && FB_CUR_SETSHAPE) {
+ if (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
/*
* Voodoo 3 and above cards use 2 monochrome cursor patterns.
* The reason is so the card can fetch 8 words at a time
@@ -1096,7 +1079,7 @@ static int tdfxfb_cursor(struct fb_info
* This reduces the number of times for access to draw the
* cursor for each screen refresh.
* Each pattern is a bitmap of 64 bit wide and 64 bit high
- * (total of 8192 bits or 1024 Kbytes). The two patterns are
+ * (total of 8192 bits or 1024 bytes). The two patterns are
* stored in such a way that pattern 0 always resides in the
* lower half (least significant 64 bits) of a 128 bit word
* and pattern 1 the upper half. If you examine the data of
@@ -1107,50 +1090,34 @@ static int tdfxfb_cursor(struct fb_info
* (128 bits) which is the maximum cursor width times two for
* the two monochrome patterns.
*/
- u8 *cursorbase = (u8 *)info->cursor.image.data;
- char *bitmap = (char *)cursor->image.data;
- char *mask = (char *)cursor->mask;
- int i, j, k, h = 0;
-
- for (i = 0; i < 64; i++) {
- if (i < cursor->image.height) {
- j = (cursor->image.width + 7) >> 3;
- k = 8 - j;
-
- for (; j > 0; j--) {
- /* Pattern 0. Copy the cursor bitmap to it */
- fb_writeb(*bitmap, cursorbase + h);
- bitmap++;
- /* Pattern 1. Copy the cursor mask to it */
- fb_writeb(*mask, cursorbase + h + 8);
- mask++;
- h++;
- }
- for (; k > 0; k--) {
- fb_writeb(0, cursorbase + h);
- fb_writeb(~0, cursorbase + h + 8);
- h++;
- }
- } else {
- fb_writel(0, cursorbase + h);
- fb_writel(0, cursorbase + h + 4);
- fb_writel(~0, cursorbase + h + 8);
- fb_writel(~0, cursorbase + h + 12);
- h += 16;
+ u8 __iomem *cursorbase = info->screen_base + info->fix.smem_len;
+ u8 *bitmap = (u8 *)cursor->image.data;
+ u8 *mask = (u8 *)cursor->mask;
+ int i;
+
+ fb_memset(cursorbase, 0, 1024);
+
+ for (i = 0; i < cursor->image.height; i++) {
+ int h = 0;
+ int j = (cursor->image.width + 7) >> 3;
+
+ for (; j > 0; j--) {
+ u8 data = *mask ^ *bitmap;
+ if (cursor->rop == ROP_COPY)
+ data = *mask & *bitmap;
+ /* Pattern 0. Copy the cursor mask to it */
+ fb_writeb(*mask, cursorbase + h);
+ mask++;
+ /* Pattern 1. Copy the cursor bitmap to it */
+ fb_writeb(data, cursorbase + h + 8);
+ bitmap++;
+ h++;
}
+ cursorbase += 16;
}
}
- /* Turn the cursor on */
- cursor->enable = 1;
- info->cursor = *cursor;
- mod_timer(&par->hwcursor.timer, jiffies + HZ / 2);
- spin_lock_irqsave(&par->DAClock, flags);
- banshee_make_room(par, 1);
- tdfx_outl(par, VIDPROCCFG, par->hwcursor.enable);
- spin_unlock_irqrestore(&par->DAClock, flags);
return 0;
}
-#endif
static struct fb_ops tdfxfb_ops = {
.owner = THIS_MODULE,
@@ -1160,6 +1127,7 @@ static struct fb_ops tdfxfb_ops = {
.fb_blank = tdfxfb_blank,
.fb_pan_display = tdfxfb_pan_display,
.fb_sync = banshee_wait_idle,
+ .fb_cursor = tdfxfb_cursor,
#ifdef CONFIG_FB_3DFX_ACCEL
.fb_fillrect = tdfxfb_fillrect,
.fb_copyarea = tdfxfb_copyarea,
@@ -1272,6 +1240,11 @@ #ifdef CONFIG_FB_3DFX_ACCEL
FBINFO_HWACCEL_IMAGEBLIT |
FBINFO_READS_FAST;
#endif
+ /* reserve 8192 bits for cursor */
+ /* the 2.4 driver says PAGE_MASK boundary is not enough for Voodoo4 */
+ if (hwcursor)
+ info->fix.smem_len = (info->fix.smem_len - 1024) &
+ (PAGE_MASK << 1);
if (!mode_option)
mode_option = "640x480@60";
@@ -1336,6 +1309,8 @@ static void tdfxfb_setup(char *options)
nopan = 1;
} else if (!strcmp(this_opt, "nowrap")) {
nowrap = 1;
+ } else if (!strcmp(this_opt, "hwcursor")) {
+ hwcursor = simple_strtoul(opt + 9, NULL, 0);
} else {
mode_option = this_opt;
}
@@ -1394,5 +1369,9 @@ MODULE_AUTHOR("Hannu Mallat <hmallat@cc.
MODULE_DESCRIPTION("3Dfx framebuffer device driver");
MODULE_LICENSE("GPL");
+module_param(hwcursor, int, 0644);
+MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
+ "(1=enable, 0=disable, default=1)");
+
module_init(tdfxfb_init);
module_exit(tdfxfb_exit);
diff --git a/include/video/tdfx.h b/include/video/tdfx.h
index 451bd46..8a2bb91 100644
--- a/include/video/tdfx.h
+++ b/include/video/tdfx.h
@@ -175,14 +175,6 @@ struct tdfx_par {
u32 palette[16];
void __iomem *regbase_virt;
unsigned long iobase;
-
- struct {
- int w, u, d;
- unsigned long enable, disable;
- struct timer_list timer;
- } hwcursor;
-
- spinlock_t DAClock;
};
#endif /* __KERNEL__ */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
reply other threads:[~2007-08-01 8:16 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46B03AC7.10505@gmail.com \
--to=adaplas@gmail.com \
--cc=akpm@osdl.org \
--cc=linux-fbdev-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.