diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /os/boot/rpcg/screen.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'os/boot/rpcg/screen.c')
| -rw-r--r-- | os/boot/rpcg/screen.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/os/boot/rpcg/screen.c b/os/boot/rpcg/screen.c new file mode 100644 index 00000000..ec420ee9 --- /dev/null +++ b/os/boot/rpcg/screen.c @@ -0,0 +1,242 @@ +#include "all.h" +#include <libg.h> +#include <gnot.h> + +enum { + Colldepth = 3, + Colmaxx = 640, + Colmaxxvis = 640, + Colmaxy = 480, +}; + +#define MINX 8 + +extern GSubfont defont0; + +struct{ + Point pos; + int bwid; +}out; + +typedef struct Mode Mode; +struct Mode { + int x; + int y; + int d; + char* aperture; + int apsize; +}; + +GBitmap gscreen; +Point gchar(GBitmap*, Point, GFont*, int, Fcode); +int setcolor(ulong, ulong, ulong, ulong); +static void lcdinit(Mode*); + +void +screeninit(void) +{ + Mode m; + + m.x = Colmaxx; + m.y = Colmaxy; + m.d = Colldepth; + m.aperture = 0; + lcdinit(&m); + if(m.aperture == 0) + return; + gscreen.ldepth = 3; + gscreen.base = (ulong*)m.aperture; + gscreen.width = Colmaxx/BY2WD; + gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy); + gscreen.clipr = gscreen.r; + /* + * For now, just use a fixed colormap: + * 0 == white and 255 == black + */ + setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); + setcolor(255, 0x00000000, 0x00000000, 0x00000000); + + gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero); + out.pos.x = MINX; + out.pos.y = 0; + out.bwid = defont0.info[' '].width; +} + +void +screenputc(int c) +{ + Fontchar *i; + Point p; + + if(gscreen.base == nil) + return; + switch(c){ + case '\n': + out.pos.x = MINX; + out.pos.y += defont0.height; + if(out.pos.y > gscreen.r.max.y-defont0.height) + out.pos.y = gscreen.r.min.y; + gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen, + Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height), + Zero); + break; + case '\t': + out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid; + if(out.pos.x >= gscreen.r.max.x) + screenputc('\n'); + break; + case '\b': + if(out.pos.x >= out.bwid+MINX){ + out.pos.x -= out.bwid; + screenputc(' '); + out.pos.x -= out.bwid; + } + break; + default: + if(out.pos.x >= gscreen.r.max.x-out.bwid) + screenputc('\n'); + c &= 0x7f; + if(c <= 0 || c >= defont0.n) + break; + i = defont0.info + c; + p = out.pos; + gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits, + Rect(i[0].x, 0, i[1].x, defont0.height), + S); + out.pos.x = p.x + i->width; + break; + } +} + +void +screenputs(char *s, int n) +{ + while(n-- > 0) + screenputc(*s++); +} + +/* + * See section 5.2.1 (page 5-6) of the MPC823 manual + */ +static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */ + 0, 0, (1<<2), 1, + (2<<2), 2, (1<<2)|1, 3, + (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1, + (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2), + (4<<2) +}; + +/* + * support for the Sharp LQ64D341 TFT colour display + */ + +enum { + COLS = 640, + ROWS = 480, + LDEPTH = 3, /* screen depth */ + LCDFREQ = 25000000, + + /* lccr */ + ClockLow = 1<<11, + OELow = 1<<10, + HsyncLow = 1<<9, + VsyncLow = 1<<8, + DataLow = 1<<7, + Passive8 = 1<<4, + DualScan = 1<<3, + IsColour = 1<<2, + IsTFT = 1<<1, + Enable = 1<<0, + + /* lchcr */ + BigEndian = 1<<24, + AT7 = 7<<21, /* access type */ + + /* sdcr */ + LAM = 1<<6, /* ``LCD aggressive mode'' */ +}; + +/* + * TO DO: most of the data could come from a table + */ +static void +lcdinit(Mode *mode) +{ + IMM *io; + int i, d; + long hz; + + io = m->iomem; + mode->y = ROWS; + mode->x = COLS; + mode->d = LDEPTH; + mode->aperture = ialloc(mode->x*mode->y, 16); + mode->apsize = mode->x*mode->y; + + io->sdcr &= ~LAM; /* MPC823 errata: turn off LAM before disabling controller */ + io->lcfaa = PADDR(mode->aperture); + io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow; + + switch(LDEPTH){ + default: + case 0: + /* monochrome/greyscale identity map */ + for(i=0; i<16; i++) + io->lcdmap[i] = i; + break; + case 2: + /* 4-bit grey scale map */ + for(i=0; i<16; i++) + io->lcdmap[0] = (i<<8)|(i<<4)|i; + break; + case 3: + /* 8-bit linear map */ + for(i=0; i<256; i++) + io->lcdmap[i] = (i<<8)|(i<<4)|i; + break; + } + + io->lcvcr = (mode->y << 11) | (1<<28) | 33; /* 2 line vsync pulse, 34 line wait between frames */ + io->lchcr = (mode->x<<10) | BigEndian | 228; /* clock cycles between lines */ + + hz = m->cpuhz; + d = hz/LCDFREQ; + if(hz/d > LCDFREQ) + d++; + if(d >= 16) + d = 16; + + /* + * enable LCD outputs + */ + io->pddat = 0; + io->pdpar = 0x1fff; +io->pdpar &= ~SIBIT(6); /* 823 bug fix? */ + io->pddir = 0x1fff; + io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17); + io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17); + io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17)); + + eieio(); + io->sccrk = KEEP_ALIVE_KEY; + eieio(); + io->sccr = (io->sccr & ~0x1F) | lcdclock[d]; + eieio(); + io->sccrk = ~KEEP_ALIVE_KEY; + eieio(); + gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */ + io->lcsr = 7; /* clear status */ + eieio(); + io->lccr |= Enable; + archbacklight(1); +} + +int +setcolor(ulong p, ulong r, ulong g, ulong b) +{ + r >>= 28; + g >>= 28; + b >>= 28; + m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b; /* TO DO: it's a function of the ldepth */ + return 1; +} |
