1*74a4d8c2SCharles.Forsyth #include "all.h"
2*74a4d8c2SCharles.Forsyth #include <libg.h>
3*74a4d8c2SCharles.Forsyth #include <gnot.h>
4*74a4d8c2SCharles.Forsyth
5*74a4d8c2SCharles.Forsyth enum {
6*74a4d8c2SCharles.Forsyth Colldepth = 3,
7*74a4d8c2SCharles.Forsyth Colmaxx = 640,
8*74a4d8c2SCharles.Forsyth Colmaxxvis = 640,
9*74a4d8c2SCharles.Forsyth Colmaxy = 480,
10*74a4d8c2SCharles.Forsyth };
11*74a4d8c2SCharles.Forsyth
12*74a4d8c2SCharles.Forsyth #define MINX 8
13*74a4d8c2SCharles.Forsyth
14*74a4d8c2SCharles.Forsyth extern GSubfont defont0;
15*74a4d8c2SCharles.Forsyth
16*74a4d8c2SCharles.Forsyth struct{
17*74a4d8c2SCharles.Forsyth Point pos;
18*74a4d8c2SCharles.Forsyth int bwid;
19*74a4d8c2SCharles.Forsyth }out;
20*74a4d8c2SCharles.Forsyth
21*74a4d8c2SCharles.Forsyth typedef struct Mode Mode;
22*74a4d8c2SCharles.Forsyth struct Mode {
23*74a4d8c2SCharles.Forsyth int x;
24*74a4d8c2SCharles.Forsyth int y;
25*74a4d8c2SCharles.Forsyth int d;
26*74a4d8c2SCharles.Forsyth char* aperture;
27*74a4d8c2SCharles.Forsyth int apsize;
28*74a4d8c2SCharles.Forsyth };
29*74a4d8c2SCharles.Forsyth
30*74a4d8c2SCharles.Forsyth GBitmap gscreen;
31*74a4d8c2SCharles.Forsyth Point gchar(GBitmap*, Point, GFont*, int, Fcode);
32*74a4d8c2SCharles.Forsyth int setcolor(ulong, ulong, ulong, ulong);
33*74a4d8c2SCharles.Forsyth static void lcdinit(Mode*);
34*74a4d8c2SCharles.Forsyth
35*74a4d8c2SCharles.Forsyth void
screeninit(void)36*74a4d8c2SCharles.Forsyth screeninit(void)
37*74a4d8c2SCharles.Forsyth {
38*74a4d8c2SCharles.Forsyth Mode m;
39*74a4d8c2SCharles.Forsyth
40*74a4d8c2SCharles.Forsyth m.x = Colmaxx;
41*74a4d8c2SCharles.Forsyth m.y = Colmaxy;
42*74a4d8c2SCharles.Forsyth m.d = Colldepth;
43*74a4d8c2SCharles.Forsyth m.aperture = 0;
44*74a4d8c2SCharles.Forsyth lcdinit(&m);
45*74a4d8c2SCharles.Forsyth if(m.aperture == 0)
46*74a4d8c2SCharles.Forsyth return;
47*74a4d8c2SCharles.Forsyth gscreen.ldepth = 3;
48*74a4d8c2SCharles.Forsyth gscreen.base = (ulong*)m.aperture;
49*74a4d8c2SCharles.Forsyth gscreen.width = Colmaxx/BY2WD;
50*74a4d8c2SCharles.Forsyth gscreen.r = Rect(0, 0, Colmaxxvis, Colmaxy);
51*74a4d8c2SCharles.Forsyth gscreen.clipr = gscreen.r;
52*74a4d8c2SCharles.Forsyth /*
53*74a4d8c2SCharles.Forsyth * For now, just use a fixed colormap:
54*74a4d8c2SCharles.Forsyth * 0 == white and 255 == black
55*74a4d8c2SCharles.Forsyth */
56*74a4d8c2SCharles.Forsyth setcolor(0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
57*74a4d8c2SCharles.Forsyth setcolor(255, 0x00000000, 0x00000000, 0x00000000);
58*74a4d8c2SCharles.Forsyth
59*74a4d8c2SCharles.Forsyth gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, Zero);
60*74a4d8c2SCharles.Forsyth out.pos.x = MINX;
61*74a4d8c2SCharles.Forsyth out.pos.y = 0;
62*74a4d8c2SCharles.Forsyth out.bwid = defont0.info[' '].width;
63*74a4d8c2SCharles.Forsyth }
64*74a4d8c2SCharles.Forsyth
65*74a4d8c2SCharles.Forsyth void
screenputc(int c)66*74a4d8c2SCharles.Forsyth screenputc(int c)
67*74a4d8c2SCharles.Forsyth {
68*74a4d8c2SCharles.Forsyth Fontchar *i;
69*74a4d8c2SCharles.Forsyth Point p;
70*74a4d8c2SCharles.Forsyth
71*74a4d8c2SCharles.Forsyth if(gscreen.base == nil)
72*74a4d8c2SCharles.Forsyth return;
73*74a4d8c2SCharles.Forsyth switch(c){
74*74a4d8c2SCharles.Forsyth case '\n':
75*74a4d8c2SCharles.Forsyth out.pos.x = MINX;
76*74a4d8c2SCharles.Forsyth out.pos.y += defont0.height;
77*74a4d8c2SCharles.Forsyth if(out.pos.y > gscreen.r.max.y-defont0.height)
78*74a4d8c2SCharles.Forsyth out.pos.y = gscreen.r.min.y;
79*74a4d8c2SCharles.Forsyth gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen,
80*74a4d8c2SCharles.Forsyth Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height),
81*74a4d8c2SCharles.Forsyth Zero);
82*74a4d8c2SCharles.Forsyth break;
83*74a4d8c2SCharles.Forsyth case '\t':
84*74a4d8c2SCharles.Forsyth out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
85*74a4d8c2SCharles.Forsyth if(out.pos.x >= gscreen.r.max.x)
86*74a4d8c2SCharles.Forsyth screenputc('\n');
87*74a4d8c2SCharles.Forsyth break;
88*74a4d8c2SCharles.Forsyth case '\b':
89*74a4d8c2SCharles.Forsyth if(out.pos.x >= out.bwid+MINX){
90*74a4d8c2SCharles.Forsyth out.pos.x -= out.bwid;
91*74a4d8c2SCharles.Forsyth screenputc(' ');
92*74a4d8c2SCharles.Forsyth out.pos.x -= out.bwid;
93*74a4d8c2SCharles.Forsyth }
94*74a4d8c2SCharles.Forsyth break;
95*74a4d8c2SCharles.Forsyth default:
96*74a4d8c2SCharles.Forsyth if(out.pos.x >= gscreen.r.max.x-out.bwid)
97*74a4d8c2SCharles.Forsyth screenputc('\n');
98*74a4d8c2SCharles.Forsyth c &= 0x7f;
99*74a4d8c2SCharles.Forsyth if(c <= 0 || c >= defont0.n)
100*74a4d8c2SCharles.Forsyth break;
101*74a4d8c2SCharles.Forsyth i = defont0.info + c;
102*74a4d8c2SCharles.Forsyth p = out.pos;
103*74a4d8c2SCharles.Forsyth gbitblt(&gscreen, Pt(p.x+i->left, p.y), defont0.bits,
104*74a4d8c2SCharles.Forsyth Rect(i[0].x, 0, i[1].x, defont0.height),
105*74a4d8c2SCharles.Forsyth S);
106*74a4d8c2SCharles.Forsyth out.pos.x = p.x + i->width;
107*74a4d8c2SCharles.Forsyth break;
108*74a4d8c2SCharles.Forsyth }
109*74a4d8c2SCharles.Forsyth }
110*74a4d8c2SCharles.Forsyth
111*74a4d8c2SCharles.Forsyth void
screenputs(char * s,int n)112*74a4d8c2SCharles.Forsyth screenputs(char *s, int n)
113*74a4d8c2SCharles.Forsyth {
114*74a4d8c2SCharles.Forsyth while(n-- > 0)
115*74a4d8c2SCharles.Forsyth screenputc(*s++);
116*74a4d8c2SCharles.Forsyth }
117*74a4d8c2SCharles.Forsyth
118*74a4d8c2SCharles.Forsyth /*
119*74a4d8c2SCharles.Forsyth * See section 5.2.1 (page 5-6) of the MPC823 manual
120*74a4d8c2SCharles.Forsyth */
121*74a4d8c2SCharles.Forsyth static uchar lcdclock[17] = { /* (a<<2)|b => divisor of (1<<a)*((b<<1)+1) */
122*74a4d8c2SCharles.Forsyth 0, 0, (1<<2), 1,
123*74a4d8c2SCharles.Forsyth (2<<2), 2, (1<<2)|1, 3,
124*74a4d8c2SCharles.Forsyth (3<<2), (1<<2)|2, (1<<2)|2, (2<<2)|1,
125*74a4d8c2SCharles.Forsyth (2<<2)|1, (1<<2)|3, (1<<2)|3, (4<<2),
126*74a4d8c2SCharles.Forsyth (4<<2)
127*74a4d8c2SCharles.Forsyth };
128*74a4d8c2SCharles.Forsyth
129*74a4d8c2SCharles.Forsyth /*
130*74a4d8c2SCharles.Forsyth * support for the Sharp LQ64D341 TFT colour display
131*74a4d8c2SCharles.Forsyth */
132*74a4d8c2SCharles.Forsyth
133*74a4d8c2SCharles.Forsyth enum {
134*74a4d8c2SCharles.Forsyth COLS = 640,
135*74a4d8c2SCharles.Forsyth ROWS = 480,
136*74a4d8c2SCharles.Forsyth LDEPTH = 3, /* screen depth */
137*74a4d8c2SCharles.Forsyth LCDFREQ = 25000000,
138*74a4d8c2SCharles.Forsyth
139*74a4d8c2SCharles.Forsyth /* lccr */
140*74a4d8c2SCharles.Forsyth ClockLow = 1<<11,
141*74a4d8c2SCharles.Forsyth OELow = 1<<10,
142*74a4d8c2SCharles.Forsyth HsyncLow = 1<<9,
143*74a4d8c2SCharles.Forsyth VsyncLow = 1<<8,
144*74a4d8c2SCharles.Forsyth DataLow = 1<<7,
145*74a4d8c2SCharles.Forsyth Passive8 = 1<<4,
146*74a4d8c2SCharles.Forsyth DualScan = 1<<3,
147*74a4d8c2SCharles.Forsyth IsColour = 1<<2,
148*74a4d8c2SCharles.Forsyth IsTFT = 1<<1,
149*74a4d8c2SCharles.Forsyth Enable = 1<<0,
150*74a4d8c2SCharles.Forsyth
151*74a4d8c2SCharles.Forsyth /* lchcr */
152*74a4d8c2SCharles.Forsyth BigEndian = 1<<24,
153*74a4d8c2SCharles.Forsyth AT7 = 7<<21, /* access type */
154*74a4d8c2SCharles.Forsyth
155*74a4d8c2SCharles.Forsyth /* sdcr */
156*74a4d8c2SCharles.Forsyth LAM = 1<<6, /* ``LCD aggressive mode'' */
157*74a4d8c2SCharles.Forsyth };
158*74a4d8c2SCharles.Forsyth
159*74a4d8c2SCharles.Forsyth /*
160*74a4d8c2SCharles.Forsyth * TO DO: most of the data could come from a table
161*74a4d8c2SCharles.Forsyth */
162*74a4d8c2SCharles.Forsyth static void
lcdinit(Mode * mode)163*74a4d8c2SCharles.Forsyth lcdinit(Mode *mode)
164*74a4d8c2SCharles.Forsyth {
165*74a4d8c2SCharles.Forsyth IMM *io;
166*74a4d8c2SCharles.Forsyth int i, d;
167*74a4d8c2SCharles.Forsyth long hz;
168*74a4d8c2SCharles.Forsyth
169*74a4d8c2SCharles.Forsyth io = m->iomem;
170*74a4d8c2SCharles.Forsyth mode->y = ROWS;
171*74a4d8c2SCharles.Forsyth mode->x = COLS;
172*74a4d8c2SCharles.Forsyth mode->d = LDEPTH;
173*74a4d8c2SCharles.Forsyth mode->aperture = ialloc(mode->x*mode->y, 16);
174*74a4d8c2SCharles.Forsyth mode->apsize = mode->x*mode->y;
175*74a4d8c2SCharles.Forsyth
176*74a4d8c2SCharles.Forsyth io->sdcr &= ~LAM; /* MPC823 errata: turn off LAM before disabling controller */
177*74a4d8c2SCharles.Forsyth io->lcfaa = PADDR(mode->aperture);
178*74a4d8c2SCharles.Forsyth io->lccr = (((mode->x*mode->y*(1<<LDEPTH)+127)/128) << 17) | (LDEPTH << 5) | IsColour | IsTFT | OELow | VsyncLow | ClockLow;
179*74a4d8c2SCharles.Forsyth
180*74a4d8c2SCharles.Forsyth switch(LDEPTH){
181*74a4d8c2SCharles.Forsyth default:
182*74a4d8c2SCharles.Forsyth case 0:
183*74a4d8c2SCharles.Forsyth /* monochrome/greyscale identity map */
184*74a4d8c2SCharles.Forsyth for(i=0; i<16; i++)
185*74a4d8c2SCharles.Forsyth io->lcdmap[i] = i;
186*74a4d8c2SCharles.Forsyth break;
187*74a4d8c2SCharles.Forsyth case 2:
188*74a4d8c2SCharles.Forsyth /* 4-bit grey scale map */
189*74a4d8c2SCharles.Forsyth for(i=0; i<16; i++)
190*74a4d8c2SCharles.Forsyth io->lcdmap[0] = (i<<8)|(i<<4)|i;
191*74a4d8c2SCharles.Forsyth break;
192*74a4d8c2SCharles.Forsyth case 3:
193*74a4d8c2SCharles.Forsyth /* 8-bit linear map */
194*74a4d8c2SCharles.Forsyth for(i=0; i<256; i++)
195*74a4d8c2SCharles.Forsyth io->lcdmap[i] = (i<<8)|(i<<4)|i;
196*74a4d8c2SCharles.Forsyth break;
197*74a4d8c2SCharles.Forsyth }
198*74a4d8c2SCharles.Forsyth
199*74a4d8c2SCharles.Forsyth io->lcvcr = (mode->y << 11) | (1<<28) | 33; /* 2 line vsync pulse, 34 line wait between frames */
200*74a4d8c2SCharles.Forsyth io->lchcr = (mode->x<<10) | BigEndian | 228; /* clock cycles between lines */
201*74a4d8c2SCharles.Forsyth
202*74a4d8c2SCharles.Forsyth hz = m->cpuhz;
203*74a4d8c2SCharles.Forsyth d = hz/LCDFREQ;
204*74a4d8c2SCharles.Forsyth if(hz/d > LCDFREQ)
205*74a4d8c2SCharles.Forsyth d++;
206*74a4d8c2SCharles.Forsyth if(d >= 16)
207*74a4d8c2SCharles.Forsyth d = 16;
208*74a4d8c2SCharles.Forsyth
209*74a4d8c2SCharles.Forsyth /*
210*74a4d8c2SCharles.Forsyth * enable LCD outputs
211*74a4d8c2SCharles.Forsyth */
212*74a4d8c2SCharles.Forsyth io->pddat = 0;
213*74a4d8c2SCharles.Forsyth io->pdpar = 0x1fff;
214*74a4d8c2SCharles.Forsyth io->pdpar &= ~SIBIT(6); /* 823 bug fix? */
215*74a4d8c2SCharles.Forsyth io->pddir = 0x1fff;
216*74a4d8c2SCharles.Forsyth io->pbpar |= IBIT(31) | IBIT(19) | IBIT(17);
217*74a4d8c2SCharles.Forsyth io->pbdir |= IBIT(31) | IBIT(19) | IBIT(17);
218*74a4d8c2SCharles.Forsyth io->pbodr &= ~(IBIT(31) | IBIT(19) | IBIT(17));
219*74a4d8c2SCharles.Forsyth
220*74a4d8c2SCharles.Forsyth eieio();
221*74a4d8c2SCharles.Forsyth io->sccrk = KEEP_ALIVE_KEY;
222*74a4d8c2SCharles.Forsyth eieio();
223*74a4d8c2SCharles.Forsyth io->sccr = (io->sccr & ~0x1F) | lcdclock[d];
224*74a4d8c2SCharles.Forsyth eieio();
225*74a4d8c2SCharles.Forsyth io->sccrk = ~KEEP_ALIVE_KEY;
226*74a4d8c2SCharles.Forsyth eieio();
227*74a4d8c2SCharles.Forsyth gscreen.width = gscreen.width; /* access external memory before enabling (mpc823 errata) */
228*74a4d8c2SCharles.Forsyth io->lcsr = 7; /* clear status */
229*74a4d8c2SCharles.Forsyth eieio();
230*74a4d8c2SCharles.Forsyth io->lccr |= Enable;
231*74a4d8c2SCharles.Forsyth archbacklight(1);
232*74a4d8c2SCharles.Forsyth }
233*74a4d8c2SCharles.Forsyth
234*74a4d8c2SCharles.Forsyth int
setcolor(ulong p,ulong r,ulong g,ulong b)235*74a4d8c2SCharles.Forsyth setcolor(ulong p, ulong r, ulong g, ulong b)
236*74a4d8c2SCharles.Forsyth {
237*74a4d8c2SCharles.Forsyth r >>= 28;
238*74a4d8c2SCharles.Forsyth g >>= 28;
239*74a4d8c2SCharles.Forsyth b >>= 28;
240*74a4d8c2SCharles.Forsyth m->iomem->lcdmap[~p&0xFF] = (r<<8) | (g<<4) | b; /* TO DO: it's a function of the ldepth */
241*74a4d8c2SCharles.Forsyth return 1;
242*74a4d8c2SCharles.Forsyth }
243