summaryrefslogtreecommitdiffstats
path: root/drivers/video/creatorfb.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
commit86464aed71025541805e7b1515541aee89879e33 (patch)
treee01a457a4912a8553bc65524aa3125d51f29f810 /drivers/video/creatorfb.c
parent88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff)
Merge with Linux 2.2.1.
Diffstat (limited to 'drivers/video/creatorfb.c')
-rw-r--r--drivers/video/creatorfb.c78
1 files changed, 73 insertions, 5 deletions
diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c
index 6c8f14b1d..69242992d 100644
--- a/drivers/video/creatorfb.c
+++ b/drivers/video/creatorfb.c
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.15 1998/09/04 15:43:40 jj Exp $
+/* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $
* creatorfb.c: Creator/Creator3D frame buffer driver
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -123,7 +123,12 @@
#define FFB_ROP_NEW 0x83
#define FFB_UCSR_FIFO_MASK 0x00000fff
+#define FFB_UCSR_FB_BUSY 0x01000000
#define FFB_UCSR_RP_BUSY 0x02000000
+#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
+#define FFB_UCSR_READ_ERR 0x40000000
+#define FFB_UCSR_FIFO_OVFL 0x80000000
+#define FFB_UCSR_ALL_ERRORS (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
struct ffb_fbc {
/* Next vertex registers */
@@ -271,6 +276,30 @@ struct ffb_fbc {
volatile u32 mer;
};
+static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n)
+{
+ int limit = 10000;
+
+ 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);
+}
+
+static __inline__ void FFBWait(struct ffb_fbc *ffb)
+{
+ int limit = 10000;
+
+ do {
+ if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0)
+ break;
+ if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
+ ffb->ucsr = FFB_UCSR_ALL_ERRORS;
+ } while(--limit > 0);
+}
+
struct ffb_dac {
volatile u32 type;
volatile u32 value;
@@ -313,6 +342,8 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
int x, y, w, h;
+ FFBWait(fbc);
+ FFBFifo(fbc, 6);
fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
fbc->drawop = FFB_DRAWOP_RECTANGLE;
@@ -337,9 +368,12 @@ static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
{
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+ FFBWait(fbc);
+ FFBFifo(fbc, 2);
fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
fbc->drawop = FFB_DRAWOP_RECTANGLE;
while (count-- > 0) {
+ FFBFifo(fbc, 4);
fbc->by = boxes[1];
fbc->bx = boxes[0];
fbc->bh = boxes[3] - boxes[1];
@@ -370,11 +404,14 @@ 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;
fbc->fontxy = xy;
+ FFBFifo(fbc, fontheight(p));
if (fontwidth(p) <= 8) {
for (i = 0; i < fontheight(p); i++)
fbc->font = *fd++ << 24;
@@ -394,6 +431,8 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
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)];
xy = fb->s.ffb.xy_margin;
@@ -408,6 +447,7 @@ 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);
fbc->fontw = 4 * fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
@@ -422,6 +462,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
fd4 = p->fontdata + ((*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++)
@@ -437,6 +478,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
} else {
while (count >= 2) {
count -= 2;
+ FFBFifo(fbc, 3);
fbc->fontw = 2 * fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
@@ -447,6 +489,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
fd2 = p->fontdata + (((*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;
@@ -456,6 +499,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
}
while (count) {
count--;
+ FFBFifo(fbc, 3);
fbc->fontw = fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
@@ -463,6 +507,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
i = ((*s++ & p->charmask) << fontheightlog(p));
else
i = ((*s++ & p->charmask) * fontheight(p));
+ FFBFifo(fbc, fontheight(p));
if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
for (i = 0; i < fontheight(p); i++)
@@ -573,10 +618,13 @@ 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);
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->pmask = 0xffffffff;
+ FFBWait(fbc);
}
static char idstring[60] __initdata = { 0 };
@@ -588,7 +636,9 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
struct display *disp = &fb->disp;
struct fbtype *type = &fb->type;
struct linux_prom64_registers regs[2*PROMREG_MAX];
- int i;
+ int i, afb = 0;
+ unsigned int btype;
+ char name[64];
if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
return NULL;
@@ -597,10 +647,22 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
if (!disp->dispsw_data)
return NULL;
memset(disp->dispsw_data, 0, 16 * sizeof(u32));
+
+ prom_getstring(fb->prom_node, "name", name, sizeof(name));
+ if (!strcmp(name, "SUNW,afb"))
+ afb = 1;
- strcpy(fb->info.modename, "Creator");
+ btype = prom_getintdefault(fb->prom_node, "board_type", 0);
- strcpy(fix->id, "Creator");
+ strcpy(fb->info.modename, "Creator");
+ if (!afb) {
+ if ((btype & 7) == 3)
+ strcpy(fix->id, "Creator 3D");
+ else
+ strcpy(fix->id, "Creator");
+ } else
+ strcpy(fix->id, "Elite 3D");
+
fix->visual = FB_VISUAL_TRUECOLOR;
fix->line_length = 8192;
fix->accel = FB_ACCEL_SUN_CREATOR;
@@ -625,6 +687,12 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
fb->switch_from_graph = ffb_switch_from_graph;
fb->fill = ffb_fill;
+ /* If there are any read errors or fifo overflow conditions,
+ * clear them now.
+ */
+ if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
+ fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS;
+
ffb_switch_from_graph(fb);
fb->physbase = regs[0].phys_addr;
@@ -640,7 +708,7 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
i = prom_getintdefault (fb->prom_node, "board_type", 8);
- sprintf(idstring, "Creator at %016lx type %d DAC %d", regs[0].phys_addr, i, fb->s.ffb.dac_rev);
+ sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
return idstring;
}