summaryrefslogtreecommitdiffstats
path: root/drivers/video/creatorfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/creatorfb.c')
-rw-r--r--drivers/video/creatorfb.c166
1 files changed, 90 insertions, 76 deletions
diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c
index 69242992d..81421a7ff 100644
--- a/drivers/video/creatorfb.c
+++ b/drivers/video/creatorfb.c
@@ -1,7 +1,7 @@
-/* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $
+/* $Id: creatorfb.c,v 1.27 1999/03/28 12:37:12 jj Exp $
* creatorfb.c: Creator/Creator3D frame buffer driver
*
- * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
#include <linux/module.h>
@@ -132,18 +132,10 @@
struct ffb_fbc {
/* Next vertex registers */
- u32 xxx1[3];
- volatile u32 alpha;
- volatile u32 red;
- volatile u32 green;
- volatile u32 blue;
- volatile u32 depth;
- volatile u32 y;
- volatile u32 x;
- u32 xxx2[2];
- volatile u32 ryf;
- volatile u32 rxf;
- u32 xxx3[2];
+ u32 xxx1[3]; volatile u32 alpha; volatile u32 red;
+ volatile u32 green; volatile u32 blue; volatile u32 depth; volatile
+ u32 y; volatile u32 x; u32 xxx2[2]; volatile u32 ryf; volatile u32
+ rxf; u32 xxx3[2];
volatile u32 dmyf;
volatile u32 dmxf;
@@ -276,16 +268,17 @@ struct ffb_fbc {
volatile u32 mer;
};
-static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n)
+static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n)
{
- int limit = 10000;
+ struct ffb_fbc *fbc;
+ int cache = fb->s.ffb.fifo_cache;
- do {
- if((ffb->ucsr & FFB_UCSR_FIFO_MASK) >= (n + 4))
- break;
- if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
- ffb->ucsr = FFB_UCSR_ALL_ERRORS;
- } while(--limit > 0);
+ if (cache - n < 0) {
+ fbc = fb->s.ffb.fbc;
+ do { cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 8;
+ } while (cache - n < 0);
+ }
+ fb->s.ffb.fifo_cache = cache - n;
}
static __inline__ void FFBWait(struct ffb_fbc *ffb)
@@ -340,40 +333,45 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
{
struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
- int x, y, w, h;
+ u64 yx, hw;
+ int fg;
- FFBWait(fbc);
- FFBFifo(fbc, 6);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
- fbc->drawop = FFB_DRAWOP_RECTANGLE;
+ fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
+ if (fg != fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 5);
+ fbc->fg = fg;
+ fb->s.ffb.fg_cache = fg;
+ } else
+ FFBFifo(fb, 4);
if (fontheightlog(p)) {
- y = sy << fontheightlog(p); h = height << fontheightlog(p);
+ yx = (u64)sy << (fontheightlog(p) + 32); hw = (u64)height << (fontheightlog(p) + 32);
} else {
- y = sy * fontheight(p); h = height * fontheight(p);
+ yx = (u64)(sy * fontheight(p)) << 32; hw = (u64)(height * fontheight(p)) << 32;
}
if (fontwidthlog(p)) {
- x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
+ yx += sx << fontwidthlog(p); hw += width << fontwidthlog(p);
} else {
- x = sx * fontwidth(p); w = width * fontwidth(p);
+ yx += sx * fontwidth(p); hw += width * fontwidth(p);
}
- fbc->by = y + fb->y_margin;
- fbc->bx = x + fb->x_margin;
- fbc->bh = h;
- fbc->bw = w;
+ *(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin;
+ *(volatile u64 *)&fbc->bh = hw;
}
static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
int count, unsigned short *boxes)
{
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+ int fg;
- FFBWait(fbc);
- FFBFifo(fbc, 2);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
- fbc->drawop = FFB_DRAWOP_RECTANGLE;
+ fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
+ if (fg != fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 1);
+ fbc->fg = fg;
+ fb->s.ffb.fg_cache = fg;
+ }
while (count-- > 0) {
- FFBFifo(fbc, 4);
+ FFBFifo(fb, 4);
fbc->by = boxes[1];
fbc->bx = boxes[0];
fbc->bh = boxes[3] - boxes[1];
@@ -388,6 +386,7 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
int i, xy;
u8 *fd;
+ u64 fgbg;
if (fontheightlog(p)) {
xy = (yy << (16 + fontheightlog(p)));
@@ -404,14 +403,16 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int
xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
else
xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
- FFBWait(fbc);
- FFBFifo(fbc, 5);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
- fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
- fbc->fontw = fontwidth(p);
- fbc->fontinc = 0x10000;
+ fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) |
+ ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+ if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 2);
+ *(volatile u64 *)&fbc->fg = fgbg;
+ *(u64 *)&fb->s.ffb.fg_cache = fgbg;
+ }
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontxy = xy;
- FFBFifo(fbc, fontheight(p));
+ fbc->fontw = fontwidth(p);
if (fontwidth(p) <= 8) {
for (i = 0; i < fontheight(p); i++)
fbc->font = *fd++ << 24;
@@ -430,11 +431,15 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
int i, xy;
u8 *fd1, *fd2, *fd3, *fd4;
-
- FFBWait(fbc);
- FFBFifo(fbc, 2);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
- fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
+ u64 fgbg;
+
+ fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) |
+ ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))];
+ if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 2);
+ *(volatile u64 *)&fbc->fg = fgbg;
+ *(u64 *)&fb->s.ffb.fg_cache = fgbg;
+ }
xy = fb->s.ffb.xy_margin;
if (fontwidthlog(p))
xy += (xx << fontwidthlog(p));
@@ -447,22 +452,20 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
if (fontwidth(p) <= 8) {
while (count >= 4) {
count -= 4;
- FFBFifo(fbc, 3);
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontw = 4 * fontwidth(p);
- fbc->fontinc = 0x10000;
fbc->fontxy = xy;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
} else {
- fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
}
- FFBFifo(fbc, fontheight(p));
if (fontwidth(p) == 8) {
for (i = 0; i < fontheight(p); i++)
fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
@@ -478,18 +481,16 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
} else {
while (count >= 2) {
count -= 2;
- FFBFifo(fbc, 3);
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontw = 2 * fontwidth(p);
- fbc->fontinc = 0x10000;
fbc->fontxy = xy;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
- fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
} else {
- fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
- fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
+ fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
}
- FFBFifo(fbc, fontheight(p));
for (i = 0; i < fontheight(p); i++) {
fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
fd1 += 2; fd2 += 2;
@@ -499,15 +500,13 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
}
while (count) {
count--;
- FFBFifo(fbc, 3);
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontw = fontwidth(p);
- fbc->fontinc = 0x10000;
fbc->fontxy = xy;
if (fontheightlog(p))
- i = ((*s++ & p->charmask) << fontheightlog(p));
+ i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
else
- i = ((*s++ & p->charmask) * fontheight(p));
- FFBFifo(fbc, fontheight(p));
+ i = ((scr_readw(s++) & p->charmask) * fontheight(p));
if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
for (i = 0; i < fontheight(p); i++)
@@ -554,8 +553,12 @@ static struct display_switch ffb_dispsw __initdata = {
static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
{
+ register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+
fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
+ fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
+ FFBWait(fbc);
}
static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
@@ -619,11 +622,16 @@ static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
FFBWait(fbc);
- FFBFifo(fbc, 4);
+ fb->s.ffb.fifo_cache = 0;
+ FFBFifo(fb, 8);
fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
fbc->fbc = 0x2000707f;
fbc->rop = FFB_ROP_NEW;
+ fbc->drawop = FFB_DRAWOP_RECTANGLE;
fbc->pmask = 0xffffffff;
+ fbc->fontinc = 0x10000;
+ fbc->fg = fb->s.ffb.fg_cache;
+ fbc->bg = fb->s.ffb.bg_cache;
FFBWait(fbc);
}
@@ -675,6 +683,7 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
disp->scrollmode = SCROLL_YREDRAW;
disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
+ fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF);
fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
fb->dispsw = ffb_dispsw;
@@ -710,5 +719,10 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
+ /* Elite3D has different DAC revision numbering, and no DAC revisions
+ have the reversed meaning of cursor enable */
+ if (afb)
+ fb->s.ffb.dac_rev = 10;
+
return idstring;
}