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