xref: /inferno-os/os/boot/mpc/screen.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
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