diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
commit | 86464aed71025541805e7b1515541aee89879e33 (patch) | |
tree | e01a457a4912a8553bc65524aa3125d51f29f810 /drivers/video/creatorfb.c | |
parent | 88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff) |
Merge with Linux 2.2.1.
Diffstat (limited to 'drivers/video/creatorfb.c')
-rw-r--r-- | drivers/video/creatorfb.c | 78 |
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; } |