2 * ti omap35 display subsystem (dss)
4 * can handle 2ⁿ bits per pixel for 0 < n ≤ 4, and 12 and 24 bits.
5 * can handle 1024×768 at 60 Hz with pixel clock of 63.5 MHz
6 * 1280×800 at 59.91 Hz with pixel clock of 71 MHz
7 * 1400×1050 lcd at 50 MHz with pixel clock of 75 MHz
8 * has 256 24-bit entries in RGB palette
11 #include "../port/lib.h"
17 #include "../port/error.h"
27 Tabstop = 4, /* should be 8 */
28 Scroll = 8, /* lines to scroll at one time */
30 * screen settings for Wid and Ht, should a bit more dynamic?
31 * http://www.epanorama.net/faq/vga2rgb/calc.html
32 * used to calculate settings.
35 // Hbp = (248-1) << 20,
51 EnableWakeup = 1 << 2,
73 // Lcden = 1 << 0, /* unused */
76 typedef struct Dispcregs Dispc;
77 typedef struct Dssregs Dss;
78 typedef struct Ioregs Ioregs;
80 struct Ioregs { /* common registers, 68 (0x44) bytes */
82 uchar _pad0[0x10-0x4];
98 struct Dssregs { /* display subsys at 0x48050000 */
102 uchar _pad3[0x5c-0x4c];
106 struct Dispcregs { /* display ctlr at 0x48050400 */
110 ulong defaultcolor[2];
122 ulong base[2]; /* should allocate both to avoid dithering */
132 ulong palette; /* gfx_table_ba */
133 uchar _pad5[0x5d4 - 0x4bc];
136 uchar _pad5[0x620 - 0x5e0];
148 { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
149 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
150 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
151 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
153 { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
154 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
155 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
156 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
161 Settings settings[] = {
162 [Res800x600] { 800, 600, 60, RGB16, 40000, 88, 40, 128, 23, 1, 5, },
163 [Res1024x768] { 1024, 768, 60, RGB16, 65000, 160, 24, 136, 29, 3, 7, },
164 [Res1280x1024] { 1280, 1024, 60, RGB16, 108000, 248, 48, 112, 38, 1, 4, },
165 [Res1400x1050] { 1400, 1050, 50, RGB16, 108000, 248, 48, 112, 38, 1, 4, }, // TODO
170 static Memdata xgdata;
172 static Memimage xgscreen =
174 { 0, 0, Wid, Ht }, /* r */
175 { 0, 0, Wid, Ht }, /* clipr */
182 Wid*(Depth/BI2BY)/BY2WD, /* width in words of a single scan line */
187 static Memimage *conscol;
188 static Memimage *back;
190 static Memsubfont *memdefont;
192 static Lock screenlock;
196 static int landscape = 0; /* screen orientation, default is 0: portrait */
197 static ushort *vscreen; /* virtual screen */
198 static Rectangle window;
200 static Dispc *dispc = (Dispc *)PHYSDISPC;
201 static Dss *dss = (Dss *)PHYSDSS;
203 static void omapscreenputs(char *s, int n);
204 static ulong rep(ulong, int);
205 static void screenputc(char *buf);
206 static void screenwin(void);
211 int swvisible; /* is the cursor visible? */
212 int swenabled; /* is the cursor supposed to be on the screen? */
213 Memimage* swback; /* screen under cursor */
214 Memimage* swimg; /* cursor image */
215 Memimage* swmask; /* cursor mask */
220 Rectangle swrect; /* screen rectangle in swback */
221 Point swpt; /* desired cursor location */
222 Point swvispt; /* actual cursor location */
223 int swvers; /* incremented each time cursor image changes */
224 int swvisvers; /* the version on the screen */
229 dispc->ctrl &= ~1; /* disable the lcd */
232 dispc->irqstat1 |= 1; /* set framedone */
235 /* the lcd never comes ready, so don't bother with this */
237 /* spin until the frame is complete, but not forever */
238 for(cnt = 50; !(dispc->irqstat1 & 1) && cnt-- > 0; )
241 delay(20); /* worst case for 1 frame, 50Hz */
247 /* should reset the dss system */
252 /* see spruf98i §15.6.7.4.2 */
258 sp = oscreen.settings;
259 dss->ctrl &= 0x78; /* choose dss clock */
260 dispc->sysconf = Midlemode | Sidlemode | EnableWakeup | Autoidle;
261 dispc->config = Loadmode;
265 dispc->defaultcolor[0] = 0; /* set background color to black? */
266 dispc->defaultcolor[1] = 0;
267 dispc->transcolor[0] = 0; /* set transparency to full */
268 dispc->transcolor[1] = 0;
270 dispc->timing_h = (sp->hbp-1) << 20 | (sp->hfp-1) << 8 |
272 dispc->timing_v = sp->vbp << 20 | sp->vfp << 8 |
275 dispc->pol_req = Ipc | Ihs | Ivs | Acb;
276 dispc->divisor = 1 << 16 | HOWMANY(432000, sp->pixelclock);
278 dispc->lcdsize = (sp->ht - 1) << 16 | (sp->wid - 1);
281 dispc->base[0] = PADDR(framebuf->pixel);
282 dispc->base[1] = PADDR(framebuf->pixel);
284 dispc->pos = 0; /* place screen in the left corner */
285 /* use the whole screen */
286 dispc->size = (sp->ht - 1) << 16 | (sp->wid - 1);
288 /* what mode does plan 9 use for fb? */
289 dispc->attrib = Burstsize | Format | Gfxenable;
291 dispc->preload = Tft;
292 dispc->fifosize = Fifosize;
293 /* 1008 is max for our Burstsize */
294 dispc->fifothr = (Fifosize - 1) << 16 | (1008 - 1);
296 /* 1 byte is one pixel (not true, we use 2 bytes per pixel) */
299 dispc->winskip = 0; /* don't skip anything */
302 // dispc->palette = PADDR(framebuf->palette);
308 dispc->ctrl = Gpout1 | Gpout0 | Tftdata | Digital | Lcd | Stntft |
332 /* Paint the image data with blue pixels */
338 for (i = nelem(framebuf->pixel) - 1; i >= 0; i--)
339 framebuf->pixel[i] = 0x1f; /* blue */
340 // memset(framebuf->pixel, ~0, sizeof framebuf->pixel); /* white */
346 blankscreen(on == 0);
355 swcursordraw(mousexy());
370 /* called from devmouse */
372 setcursor(Cursor* curs)
374 oscreen.Cursor = *curs;
378 /* called from main and possibly later from devdss to change resolution */
382 static int first = 1;
385 iprint("screeninit...");
386 oscreen.settings = &settings[Res1280x1024];
391 /* mode is 16*32 = 512 */
392 framebuf = xspanalloc(sizeof *framebuf, 16*32, 0);
399 memdefont = getmemdefont();
404 xgdata.bdata = (uchar *)framebuf->pixel;
407 gscreen->r = Rect(0, 0, Wid, Ht);
408 gscreen->clipr = gscreen->r;
409 /* width, in words, of a single scan line */
410 gscreen->width = Wid * (Depth / BI2BY) / BY2WD;
411 flushmemscreen(gscreen->r);
413 blanktime = 3; /* minutes */
416 iprint("on: blue for 3 seconds...");
420 screenwin(); /* draw border & top orange bar */
421 screenputs = omapscreenputs;
422 iprint("screen: frame buffer at %#p for %dx%d\n",
423 framebuf, oscreen.settings->wid, oscreen.settings->ht);
426 swcursorinit(); /* needs gscreen set */
433 /* flushmemscreen should change buffer? */
435 flushmemscreen(Rectangle r)
447 if (rectclip(&r, gscreen->r) == 0)
449 start = (ulong)&framebuf->pixel[r.min.y*Wid + r.min.x];
450 end = (ulong)&framebuf->pixel[(r.max.y - 1)*Wid + r.max.x -1];
451 cachedwbse((ulong *)start, end - start);
455 * export screen to devdraw
458 attachscreen(Rectangle *r, ulong *chan, int *d, int *width, int *softscreen)
462 *chan = gscreen->chan;
463 *width = gscreen->width;
464 *softscreen = (landscape == 0);
465 return (uchar *)gscreen->data->bdata;
469 getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
475 setcolor(ulong p, ulong r, ulong g, ulong b)
482 blankscreen(int blank)
493 omapscreenputs(char *s, int n)
500 /* don't deadlock trying to print in interrupt */
501 if (!canlock(&screenlock))
502 return; /* discard s */
507 i = chartorune(&r, s);
530 memsetchan(gscreen, RGB16);
535 orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
536 orange->flags |= Frepl;
537 orange->clipr = gscreen->r;
538 orange->data->bdata[0] = 0x40; /* magic: colour? */
539 orange->data->bdata[1] = 0xfd; /* magic: colour? */
541 w = memdefont->info[' '].width;
542 h = memdefont->height;
544 r = insetrect(gscreen->r, 4);
546 memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
547 window = insetrect(r, 4);
548 memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
550 memimagedraw(gscreen, Rect(window.min.x, window.min.y,
551 window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
552 freememimage(orange);
553 window = insetrect(window, 5);
555 greet = " Plan 9 Console ";
556 p = addpt(window.min, Pt(10, 0));
557 q = memsubfontwidth(memdefont, greet);
558 memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
560 window.min.y += h + 6;
562 window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
572 /* move window contents up Scroll text lines */
574 r = Rpt(window.min, Pt(window.max.x, window.max.y - o));
575 p = Pt(window.min.x, window.min.y + o);
576 memimagedraw(gscreen, r, gscreen, p, nil, p, S);
579 /* clear the bottom Scroll text lines */
580 r = Rpt(Pt(window.min.x, window.max.y - o), window.max);
581 memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
588 screenputc(char *buf)
595 static int xbuf[256];
597 if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
602 if (curpos.y + h >= window.max.y)
609 curpos.x = window.min.x;
612 p = memsubfontwidth(memdefont, " ");
614 if (curpos.x >= window.max.x - Tabstop * w)
617 pos = (curpos.x - window.min.x) / w;
618 pos = Tabstop - pos % Tabstop;
620 r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
621 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
629 r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
630 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
637 p = memsubfontwidth(memdefont, buf);
640 if (curpos.x >= window.max.x - w)
644 r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
645 memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
646 memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);