193631029SDavid du Colombier /*
293631029SDavid du Colombier * ti omap35 display subsystem (dss)
393631029SDavid du Colombier *
493631029SDavid du Colombier * can handle 2ⁿ bits per pixel for 0 < n ≤ 4, and 12 and 24 bits.
593631029SDavid du Colombier * can handle 1024×768 at 60 Hz with pixel clock of 63.5 MHz
693631029SDavid du Colombier * 1280×800 at 59.91 Hz with pixel clock of 71 MHz
793631029SDavid du Colombier * 1400×1050 lcd at 50 MHz with pixel clock of 75 MHz
893631029SDavid du Colombier * has 256 24-bit entries in RGB palette
993631029SDavid du Colombier */
1093631029SDavid du Colombier #include "u.h"
1193631029SDavid du Colombier #include "../port/lib.h"
1293631029SDavid du Colombier #include "mem.h"
1393631029SDavid du Colombier #include "dat.h"
1493631029SDavid du Colombier #include "fns.h"
1593631029SDavid du Colombier #include "io.h"
1693631029SDavid du Colombier #include "ureg.h"
1793631029SDavid du Colombier #include "../port/error.h"
1893631029SDavid du Colombier
1993631029SDavid du Colombier #define Image IMAGE
2093631029SDavid du Colombier #include <draw.h>
2193631029SDavid du Colombier #include <memdraw.h>
2293631029SDavid du Colombier #include <cursor.h>
2393631029SDavid du Colombier #include "screen.h"
2493631029SDavid du Colombier // #include "gamma.h"
2593631029SDavid du Colombier
2693631029SDavid du Colombier enum {
2793631029SDavid du Colombier Tabstop = 4, /* should be 8 */
28634d7e5aSDavid du Colombier Scroll = 8, /* lines to scroll at one time */
2993631029SDavid du Colombier /*
3093631029SDavid du Colombier * screen settings for Wid and Ht, should a bit more dynamic?
3193631029SDavid du Colombier * http://www.epanorama.net/faq/vga2rgb/calc.html
3293631029SDavid du Colombier * used to calculate settings.
3393631029SDavid du Colombier */
3493631029SDavid du Colombier
3593631029SDavid du Colombier // Hbp = (248-1) << 20,
3693631029SDavid du Colombier // Hfp = (48-1) << 8,
3793631029SDavid du Colombier // Hsw = 112-1,
3893631029SDavid du Colombier
3993631029SDavid du Colombier // Vbp = 38 << 20,
4093631029SDavid du Colombier // Vfp = 1 << 8,
4193631029SDavid du Colombier // Vsw = 3,
4293631029SDavid du Colombier
4393631029SDavid du Colombier Tft = 0x60,
4493631029SDavid du Colombier
4593631029SDavid du Colombier Loadmode = 2 << 1,
4693631029SDavid du Colombier Fifosize = 0x400,
4793631029SDavid du Colombier
4893631029SDavid du Colombier /* dispc sysconfig */
4993631029SDavid du Colombier Midlemode = 2 << 12,
5093631029SDavid du Colombier Sidlemode = 2 << 3,
5193631029SDavid du Colombier EnableWakeup = 1 << 2,
5293631029SDavid du Colombier Autoidle = 1 << 0,
5393631029SDavid du Colombier
5493631029SDavid du Colombier /* dispc pool_freq */
5593631029SDavid du Colombier Ipc = 1 << 14,
5693631029SDavid du Colombier Ihs = 1 << 13,
5793631029SDavid du Colombier Ivs = 1 << 12,
5893631029SDavid du Colombier Acb = 0x28,
5993631029SDavid du Colombier
6093631029SDavid du Colombier /* gfx attribs */
6193631029SDavid du Colombier Burstsize = 2 << 6,
6293631029SDavid du Colombier Format = 6 << 1,
6393631029SDavid du Colombier Gfxenable = 1 << 0,
6493631029SDavid du Colombier
6593631029SDavid du Colombier /* dispc control */
6693631029SDavid du Colombier Gpout1 = 1 << 16,
6793631029SDavid du Colombier Gpout0 = 1 << 15,
6893631029SDavid du Colombier Tftdata = 3 << 8,
6993631029SDavid du Colombier Digital = 1 << 6,
7093631029SDavid du Colombier Lcd = 1 << 5,
7193631029SDavid du Colombier Stntft = 1 << 3,
7293631029SDavid du Colombier Digitalen = 1 << 1,
7393631029SDavid du Colombier // Lcden = 1 << 0, /* unused */
7493631029SDavid du Colombier };
7593631029SDavid du Colombier
7693631029SDavid du Colombier typedef struct Dispcregs Dispc;
7793631029SDavid du Colombier typedef struct Dssregs Dss;
7893631029SDavid du Colombier typedef struct Ioregs Ioregs;
7993631029SDavid du Colombier
8093631029SDavid du Colombier struct Ioregs { /* common registers, 68 (0x44) bytes */
8193631029SDavid du Colombier ulong rev;
8293631029SDavid du Colombier uchar _pad0[0x10-0x4];
8393631029SDavid du Colombier ulong sysconf;
8493631029SDavid du Colombier ulong sysstat;
8593631029SDavid du Colombier ulong irqstat1;
8693631029SDavid du Colombier
8793631029SDavid du Colombier /* Dispc only regs */
8893631029SDavid du Colombier ulong irqen1;
8993631029SDavid du Colombier ulong wkupen;
9093631029SDavid du Colombier ulong _pad1;
9193631029SDavid du Colombier ulong irqsts2;
9293631029SDavid du Colombier ulong irqen2;
9393631029SDavid du Colombier ulong _pad2[4];
9493631029SDavid du Colombier
9593631029SDavid du Colombier ulong ctrl;
9693631029SDavid du Colombier };
9793631029SDavid du Colombier
9893631029SDavid du Colombier struct Dssregs { /* display subsys at 0x48050000 */
9993631029SDavid du Colombier Ioregs;
10093631029SDavid du Colombier ulong sdicrtl;
10193631029SDavid du Colombier ulong pllcrtl;
10293631029SDavid du Colombier uchar _pad3[0x5c-0x4c];
10393631029SDavid du Colombier ulong sdistat;
10493631029SDavid du Colombier };
10593631029SDavid du Colombier
10693631029SDavid du Colombier struct Dispcregs { /* display ctlr at 0x48050400 */
10793631029SDavid du Colombier Ioregs;
10893631029SDavid du Colombier ulong config;
10993631029SDavid du Colombier ulong _pad3;
11093631029SDavid du Colombier ulong defaultcolor[2];
11193631029SDavid du Colombier ulong transcolor[2];
11293631029SDavid du Colombier ulong linestat;
11393631029SDavid du Colombier ulong linenum;
11493631029SDavid du Colombier ulong timing_h;
11593631029SDavid du Colombier ulong timing_v;
11693631029SDavid du Colombier ulong pol_req;
11793631029SDavid du Colombier ulong divisor;
11893631029SDavid du Colombier ulong alpha;
11993631029SDavid du Colombier ulong digsize;
12093631029SDavid du Colombier ulong lcdsize;
12193631029SDavid du Colombier
12293631029SDavid du Colombier ulong base[2]; /* should allocate both to avoid dithering */
12393631029SDavid du Colombier ulong pos;
12493631029SDavid du Colombier ulong size;
12593631029SDavid du Colombier ulong _pad4[4];
12693631029SDavid du Colombier ulong attrib;
12793631029SDavid du Colombier ulong fifothr;
12893631029SDavid du Colombier ulong fifosize;
12993631029SDavid du Colombier ulong rowinc;
13093631029SDavid du Colombier ulong pixelinc;
13193631029SDavid du Colombier ulong winskip;
13293631029SDavid du Colombier ulong palette; /* gfx_table_ba */
13393631029SDavid du Colombier uchar _pad5[0x5d4 - 0x4bc];
13493631029SDavid du Colombier
13593631029SDavid du Colombier ulong datacycle[3];
13693631029SDavid du Colombier uchar _pad5[0x620 - 0x5e0];
13793631029SDavid du Colombier
13893631029SDavid du Colombier ulong cprcoefr;
13993631029SDavid du Colombier ulong cprcoefg;
14093631029SDavid du Colombier ulong cprcoefb;
14193631029SDavid du Colombier ulong preload;
14293631029SDavid du Colombier };
14393631029SDavid du Colombier
14493631029SDavid du Colombier int drawdebug;
14593631029SDavid du Colombier Point ZP = {0, 0};
14693631029SDavid du Colombier Cursor arrow = {
14793631029SDavid du Colombier { -1, -1 },
14893631029SDavid du Colombier { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
14993631029SDavid du Colombier 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
15093631029SDavid du Colombier 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
15193631029SDavid du Colombier 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
15293631029SDavid du Colombier },
15393631029SDavid du Colombier { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
15493631029SDavid du Colombier 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
15593631029SDavid du Colombier 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
15693631029SDavid du Colombier 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
15793631029SDavid du Colombier },
15893631029SDavid du Colombier };
15993631029SDavid du Colombier
16093631029SDavid du Colombier OScreen oscreen;
161*5efba406SDavid du Colombier Settings settings[] = {
162*5efba406SDavid du Colombier [Res800x600] { 800, 600, 60, RGB16, 40000, 88, 40, 128, 23, 1, 5, },
163*5efba406SDavid du Colombier [Res1024x768] { 1024, 768, 60, RGB16, 65000, 160, 24, 136, 29, 3, 7, },
164*5efba406SDavid du Colombier [Res1280x1024] { 1280, 1024, 60, RGB16, 108000, 248, 48, 112, 38, 1, 4, },
165*5efba406SDavid du Colombier [Res1400x1050] { 1400, 1050, 50, RGB16, 108000, 248, 48, 112, 38, 1, 4, }, // TODO
16693631029SDavid du Colombier };
167bacfa46cSDavid du Colombier Omap3fb *framebuf;
16893631029SDavid du Colombier Memimage *gscreen;
16993631029SDavid du Colombier
17093631029SDavid du Colombier static Memdata xgdata;
17193631029SDavid du Colombier
17293631029SDavid du Colombier static Memimage xgscreen =
17393631029SDavid du Colombier {
17493631029SDavid du Colombier { 0, 0, Wid, Ht }, /* r */
17593631029SDavid du Colombier { 0, 0, Wid, Ht }, /* clipr */
17693631029SDavid du Colombier Depth, /* depth */
17793631029SDavid du Colombier 3, /* nchan */
17893631029SDavid du Colombier RGB16, /* chan */
17993631029SDavid du Colombier nil, /* cmap */
18093631029SDavid du Colombier &xgdata, /* data */
18193631029SDavid du Colombier 0, /* zero */
18293631029SDavid du Colombier Wid*(Depth/BI2BY)/BY2WD, /* width in words of a single scan line */
18393631029SDavid du Colombier 0, /* layer */
18493631029SDavid du Colombier 0, /* flags */
18593631029SDavid du Colombier };
18693631029SDavid du Colombier
18793631029SDavid du Colombier static Memimage *conscol;
18893631029SDavid du Colombier static Memimage *back;
18993631029SDavid du Colombier
19093631029SDavid du Colombier static Memsubfont *memdefont;
19193631029SDavid du Colombier
19293631029SDavid du Colombier static Lock screenlock;
19393631029SDavid du Colombier
19493631029SDavid du Colombier static Point curpos;
19593631029SDavid du Colombier static int h, w;
19693631029SDavid du Colombier static int landscape = 0; /* screen orientation, default is 0: portrait */
19793631029SDavid du Colombier static ushort *vscreen; /* virtual screen */
19893631029SDavid du Colombier static Rectangle window;
19993631029SDavid du Colombier
20093631029SDavid du Colombier static Dispc *dispc = (Dispc *)PHYSDISPC;
20193631029SDavid du Colombier static Dss *dss = (Dss *)PHYSDSS;
20293631029SDavid du Colombier
20393631029SDavid du Colombier static void omapscreenputs(char *s, int n);
20493631029SDavid du Colombier static ulong rep(ulong, int);
20593631029SDavid du Colombier static void screenputc(char *buf);
20693631029SDavid du Colombier static void screenwin(void);
20793631029SDavid du Colombier
208*5efba406SDavid du Colombier /*
209*5efba406SDavid du Colombier * Software cursor.
210*5efba406SDavid du Colombier */
211*5efba406SDavid du Colombier int swvisible; /* is the cursor visible? */
212*5efba406SDavid du Colombier int swenabled; /* is the cursor supposed to be on the screen? */
213*5efba406SDavid du Colombier Memimage* swback; /* screen under cursor */
214*5efba406SDavid du Colombier Memimage* swimg; /* cursor image */
215*5efba406SDavid du Colombier Memimage* swmask; /* cursor mask */
216*5efba406SDavid du Colombier Memimage* swimg1;
217*5efba406SDavid du Colombier Memimage* swmask1;
218*5efba406SDavid du Colombier
219*5efba406SDavid du Colombier Point swoffset;
220*5efba406SDavid du Colombier Rectangle swrect; /* screen rectangle in swback */
221*5efba406SDavid du Colombier Point swpt; /* desired cursor location */
222*5efba406SDavid du Colombier Point swvispt; /* actual cursor location */
223*5efba406SDavid du Colombier int swvers; /* incremented each time cursor image changes */
224*5efba406SDavid du Colombier int swvisvers; /* the version on the screen */
225*5efba406SDavid du Colombier
22693631029SDavid du Colombier static void
lcdoff(void)22793631029SDavid du Colombier lcdoff(void)
22893631029SDavid du Colombier {
22993631029SDavid du Colombier dispc->ctrl &= ~1; /* disable the lcd */
23093631029SDavid du Colombier coherence();
23193631029SDavid du Colombier
23293631029SDavid du Colombier dispc->irqstat1 |= 1; /* set framedone */
23393631029SDavid du Colombier coherence();
23493631029SDavid du Colombier
23593631029SDavid du Colombier /* the lcd never comes ready, so don't bother with this */
23693631029SDavid du Colombier #ifdef notdef
23793631029SDavid du Colombier /* spin until the frame is complete, but not forever */
23893631029SDavid du Colombier for(cnt = 50; !(dispc->irqstat1 & 1) && cnt-- > 0; )
23993631029SDavid du Colombier delay(10);
24093631029SDavid du Colombier #endif
24193631029SDavid du Colombier delay(20); /* worst case for 1 frame, 50Hz */
24293631029SDavid du Colombier }
24393631029SDavid du Colombier
24493631029SDavid du Colombier static void
dssstart(void)24593631029SDavid du Colombier dssstart(void)
24693631029SDavid du Colombier {
24793631029SDavid du Colombier /* should reset the dss system */
24893631029SDavid du Colombier dss->sysconf |= 1;
249634d7e5aSDavid du Colombier coherence();
25093631029SDavid du Colombier }
25193631029SDavid du Colombier
252*5efba406SDavid du Colombier /* see spruf98i §15.6.7.4.2 */
25393631029SDavid du Colombier static void
configdispc(void)25493631029SDavid du Colombier configdispc(void)
25593631029SDavid du Colombier {
256*5efba406SDavid du Colombier Settings *sp;
257*5efba406SDavid du Colombier
258*5efba406SDavid du Colombier sp = oscreen.settings;
25993631029SDavid du Colombier dss->ctrl &= 0x78; /* choose dss clock */
26093631029SDavid du Colombier dispc->sysconf = Midlemode | Sidlemode | EnableWakeup | Autoidle;
26193631029SDavid du Colombier dispc->config = Loadmode;
26293631029SDavid du Colombier coherence();
26393631029SDavid du Colombier
26493631029SDavid du Colombier /* pll */
26593631029SDavid du Colombier dispc->defaultcolor[0] = 0; /* set background color to black? */
26693631029SDavid du Colombier dispc->defaultcolor[1] = 0;
26793631029SDavid du Colombier dispc->transcolor[0] = 0; /* set transparency to full */
26893631029SDavid du Colombier dispc->transcolor[1] = 0;
26993631029SDavid du Colombier
270*5efba406SDavid du Colombier dispc->timing_h = (sp->hbp-1) << 20 | (sp->hfp-1) << 8 |
271*5efba406SDavid du Colombier (sp->hsw-1);
272*5efba406SDavid du Colombier dispc->timing_v = sp->vbp << 20 | sp->vfp << 8 |
273*5efba406SDavid du Colombier (sp->vsw-1);
27493631029SDavid du Colombier
27593631029SDavid du Colombier dispc->pol_req = Ipc | Ihs | Ivs | Acb;
276*5efba406SDavid du Colombier dispc->divisor = 1 << 16 | HOWMANY(432000, sp->pixelclock);
27793631029SDavid du Colombier
278*5efba406SDavid du Colombier dispc->lcdsize = (sp->ht - 1) << 16 | (sp->wid - 1);
27993631029SDavid du Colombier coherence();
28093631029SDavid du Colombier
28193631029SDavid du Colombier dispc->base[0] = PADDR(framebuf->pixel);
28293631029SDavid du Colombier dispc->base[1] = PADDR(framebuf->pixel);
28393631029SDavid du Colombier
28493631029SDavid du Colombier dispc->pos = 0; /* place screen in the left corner */
28593631029SDavid du Colombier /* use the whole screen */
286*5efba406SDavid du Colombier dispc->size = (sp->ht - 1) << 16 | (sp->wid - 1);
28793631029SDavid du Colombier
28893631029SDavid du Colombier /* what mode does plan 9 use for fb? */
28993631029SDavid du Colombier dispc->attrib = Burstsize | Format | Gfxenable;
29093631029SDavid du Colombier
29193631029SDavid du Colombier dispc->preload = Tft;
29293631029SDavid du Colombier dispc->fifosize = Fifosize;
29393631029SDavid du Colombier /* 1008 is max for our Burstsize */
29493631029SDavid du Colombier dispc->fifothr = (Fifosize - 1) << 16 | (1008 - 1);
29593631029SDavid du Colombier
29693631029SDavid du Colombier /* 1 byte is one pixel (not true, we use 2 bytes per pixel) */
29793631029SDavid du Colombier dispc->rowinc = 1;
29893631029SDavid du Colombier dispc->pixelinc = 1;
29993631029SDavid du Colombier dispc->winskip = 0; /* don't skip anything */
30093631029SDavid du Colombier coherence();
30193631029SDavid du Colombier
30293631029SDavid du Colombier // dispc->palette = PADDR(framebuf->palette);
30393631029SDavid du Colombier }
30493631029SDavid du Colombier
30593631029SDavid du Colombier static void
lcdon(int enable)30693631029SDavid du Colombier lcdon(int enable)
30793631029SDavid du Colombier {
30893631029SDavid du Colombier dispc->ctrl = Gpout1 | Gpout0 | Tftdata | Digital | Lcd | Stntft |
30993631029SDavid du Colombier Digitalen | enable;
31093631029SDavid du Colombier coherence();
31193631029SDavid du Colombier delay(10);
31293631029SDavid du Colombier }
31393631029SDavid du Colombier
31493631029SDavid du Colombier static void
lcdstop(void)315634d7e5aSDavid du Colombier lcdstop(void)
31693631029SDavid du Colombier {
31793631029SDavid du Colombier configscreengpio();
31893631029SDavid du Colombier screenclockson();
31993631029SDavid du Colombier
32093631029SDavid du Colombier lcdoff();
321634d7e5aSDavid du Colombier }
322634d7e5aSDavid du Colombier
323634d7e5aSDavid du Colombier static void
lcdinit(void)324634d7e5aSDavid du Colombier lcdinit(void)
325634d7e5aSDavid du Colombier {
326634d7e5aSDavid du Colombier lcdstop();
327634d7e5aSDavid du Colombier
32893631029SDavid du Colombier dssstart();
32993631029SDavid du Colombier configdispc();
33093631029SDavid du Colombier }
33193631029SDavid du Colombier
33293631029SDavid du Colombier /* Paint the image data with blue pixels */
33393631029SDavid du Colombier void
screentest(void)33493631029SDavid du Colombier screentest(void)
33593631029SDavid du Colombier {
336bacfa46cSDavid du Colombier int i;
33793631029SDavid du Colombier
338bacfa46cSDavid du Colombier for (i = nelem(framebuf->pixel) - 1; i >= 0; i--)
339bacfa46cSDavid du Colombier framebuf->pixel[i] = 0x1f; /* blue */
34093631029SDavid du Colombier // memset(framebuf->pixel, ~0, sizeof framebuf->pixel); /* white */
34193631029SDavid du Colombier }
34293631029SDavid du Colombier
34393631029SDavid du Colombier void
screenpower(int on)34493631029SDavid du Colombier screenpower(int on)
34593631029SDavid du Colombier {
34693631029SDavid du Colombier blankscreen(on == 0);
34793631029SDavid du Colombier }
34893631029SDavid du Colombier
349*5efba406SDavid du Colombier /*
350*5efba406SDavid du Colombier * called with drawlock locked for us, most of the time.
351*5efba406SDavid du Colombier * kernel prints at inopportune times might mean we don't
352*5efba406SDavid du Colombier * hold the lock, but memimagedraw is now reentrant so
353*5efba406SDavid du Colombier * that should be okay: worst case we get cursor droppings.
354*5efba406SDavid du Colombier */
355*5efba406SDavid du Colombier void
swcursorhide(void)356*5efba406SDavid du Colombier swcursorhide(void)
35793631029SDavid du Colombier {
358*5efba406SDavid du Colombier if(swvisible == 0)
359*5efba406SDavid du Colombier return;
360*5efba406SDavid du Colombier if(swback == nil)
361*5efba406SDavid du Colombier return;
362*5efba406SDavid du Colombier swvisible = 0;
363*5efba406SDavid du Colombier memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
364*5efba406SDavid du Colombier flushmemscreen(swrect);
365*5efba406SDavid du Colombier }
366*5efba406SDavid du Colombier
367*5efba406SDavid du Colombier void
swcursoravoid(Rectangle r)368*5efba406SDavid du Colombier swcursoravoid(Rectangle r)
369*5efba406SDavid du Colombier {
370*5efba406SDavid du Colombier if(swvisible && rectXrect(r, swrect))
371*5efba406SDavid du Colombier swcursorhide();
372*5efba406SDavid du Colombier }
373*5efba406SDavid du Colombier
374*5efba406SDavid du Colombier void
swcursordraw(void)375*5efba406SDavid du Colombier swcursordraw(void)
376*5efba406SDavid du Colombier {
377*5efba406SDavid du Colombier if(swvisible)
378*5efba406SDavid du Colombier return;
379*5efba406SDavid du Colombier if(swenabled == 0)
380*5efba406SDavid du Colombier return;
381*5efba406SDavid du Colombier if(swback == nil || swimg1 == nil || swmask1 == nil)
382*5efba406SDavid du Colombier return;
383*5efba406SDavid du Colombier // assert(!canqlock(&drawlock)); // assertion fails on omap
384*5efba406SDavid du Colombier swvispt = swpt;
385*5efba406SDavid du Colombier swvisvers = swvers;
386*5efba406SDavid du Colombier swrect = rectaddpt(Rect(0,0,16,16), swvispt);
387*5efba406SDavid du Colombier memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
388*5efba406SDavid du Colombier memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
389*5efba406SDavid du Colombier flushmemscreen(swrect);
390*5efba406SDavid du Colombier swvisible = 1;
391*5efba406SDavid du Colombier }
392*5efba406SDavid du Colombier
393*5efba406SDavid du Colombier int
cursoron(int dolock)394*5efba406SDavid du Colombier cursoron(int dolock)
395*5efba406SDavid du Colombier {
396*5efba406SDavid du Colombier if (dolock)
397*5efba406SDavid du Colombier lock(&oscreen);
398*5efba406SDavid du Colombier cursoroff(0);
399*5efba406SDavid du Colombier swcursordraw();
400*5efba406SDavid du Colombier if (dolock)
401*5efba406SDavid du Colombier unlock(&oscreen);
40293631029SDavid du Colombier return 0;
40393631029SDavid du Colombier }
40493631029SDavid du Colombier
40593631029SDavid du Colombier void
cursoroff(int dolock)406*5efba406SDavid du Colombier cursoroff(int dolock)
40793631029SDavid du Colombier {
408*5efba406SDavid du Colombier if (dolock)
409*5efba406SDavid du Colombier lock(&oscreen);
410*5efba406SDavid du Colombier swcursorhide();
411*5efba406SDavid du Colombier if (dolock)
412*5efba406SDavid du Colombier unlock(&oscreen);
41393631029SDavid du Colombier }
41493631029SDavid du Colombier
41593631029SDavid du Colombier void
swload(Cursor * curs)416*5efba406SDavid du Colombier swload(Cursor *curs)
41793631029SDavid du Colombier {
418*5efba406SDavid du Colombier uchar *ip, *mp;
419*5efba406SDavid du Colombier int i, j, set, clr;
42093631029SDavid du Colombier
421*5efba406SDavid du Colombier if(!swimg || !swmask || !swimg1 || !swmask1)
422*5efba406SDavid du Colombier return;
423*5efba406SDavid du Colombier /*
424*5efba406SDavid du Colombier * Build cursor image and mask.
425*5efba406SDavid du Colombier * Image is just the usual cursor image
426*5efba406SDavid du Colombier * but mask is a transparent alpha mask.
427*5efba406SDavid du Colombier *
428*5efba406SDavid du Colombier * The 16x16x8 memimages do not have
429*5efba406SDavid du Colombier * padding at the end of their scan lines.
430*5efba406SDavid du Colombier */
431*5efba406SDavid du Colombier ip = byteaddr(swimg, ZP);
432*5efba406SDavid du Colombier mp = byteaddr(swmask, ZP);
433*5efba406SDavid du Colombier for(i=0; i<32; i++){
434*5efba406SDavid du Colombier set = curs->set[i];
435*5efba406SDavid du Colombier clr = curs->clr[i];
436*5efba406SDavid du Colombier for(j=0x80; j; j>>=1){
437*5efba406SDavid du Colombier *ip++ = set&j ? 0x00 : 0xFF;
438*5efba406SDavid du Colombier *mp++ = (clr|set)&j ? 0xFF : 0x00;
439*5efba406SDavid du Colombier }
440*5efba406SDavid du Colombier }
441*5efba406SDavid du Colombier swoffset = curs->offset;
442*5efba406SDavid du Colombier swvers++;
443*5efba406SDavid du Colombier memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
444*5efba406SDavid du Colombier memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
445*5efba406SDavid du Colombier }
446*5efba406SDavid du Colombier
447*5efba406SDavid du Colombier /* called from devmouse */
448*5efba406SDavid du Colombier void
setcursor(Cursor * curs)449*5efba406SDavid du Colombier setcursor(Cursor* curs)
450*5efba406SDavid du Colombier {
451*5efba406SDavid du Colombier cursoroff(1);
452*5efba406SDavid du Colombier oscreen.Cursor = *curs;
453*5efba406SDavid du Colombier swload(curs);
454*5efba406SDavid du Colombier cursoron(1);
455*5efba406SDavid du Colombier }
456*5efba406SDavid du Colombier
457*5efba406SDavid du Colombier int
swmove(Point p)458*5efba406SDavid du Colombier swmove(Point p)
459*5efba406SDavid du Colombier {
460*5efba406SDavid du Colombier swpt = addpt(p, swoffset);
461*5efba406SDavid du Colombier return 0;
462*5efba406SDavid du Colombier }
463*5efba406SDavid du Colombier
464*5efba406SDavid du Colombier void
swcursorclock(void)465*5efba406SDavid du Colombier swcursorclock(void)
466*5efba406SDavid du Colombier {
467*5efba406SDavid du Colombier int x;
468*5efba406SDavid du Colombier
469*5efba406SDavid du Colombier if(!swenabled)
470*5efba406SDavid du Colombier return;
471*5efba406SDavid du Colombier swmove(mousexy());
472*5efba406SDavid du Colombier if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
473*5efba406SDavid du Colombier return;
474*5efba406SDavid du Colombier
475*5efba406SDavid du Colombier x = splhi();
476*5efba406SDavid du Colombier if(swenabled)
477*5efba406SDavid du Colombier if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
478*5efba406SDavid du Colombier if(canqlock(&drawlock)){
479*5efba406SDavid du Colombier swcursorhide();
480*5efba406SDavid du Colombier swcursordraw();
481*5efba406SDavid du Colombier qunlock(&drawlock);
482*5efba406SDavid du Colombier }
483*5efba406SDavid du Colombier splx(x);
484*5efba406SDavid du Colombier }
485*5efba406SDavid du Colombier
486*5efba406SDavid du Colombier void
swcursorinit(void)487*5efba406SDavid du Colombier swcursorinit(void)
488*5efba406SDavid du Colombier {
489*5efba406SDavid du Colombier static int init;
490*5efba406SDavid du Colombier
491*5efba406SDavid du Colombier if(!init){
492*5efba406SDavid du Colombier init = 1;
493*5efba406SDavid du Colombier addclock0link(swcursorclock, 10);
494*5efba406SDavid du Colombier }
495*5efba406SDavid du Colombier if(swback){
496*5efba406SDavid du Colombier freememimage(swback);
497*5efba406SDavid du Colombier freememimage(swmask);
498*5efba406SDavid du Colombier freememimage(swmask1);
499*5efba406SDavid du Colombier freememimage(swimg);
500*5efba406SDavid du Colombier freememimage(swimg1);
501*5efba406SDavid du Colombier }
502*5efba406SDavid du Colombier
503*5efba406SDavid du Colombier swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
504*5efba406SDavid du Colombier swmask = allocmemimage(Rect(0,0,16,16), GREY8);
505*5efba406SDavid du Colombier swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
506*5efba406SDavid du Colombier swimg = allocmemimage(Rect(0,0,16,16), GREY8);
507*5efba406SDavid du Colombier swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
508*5efba406SDavid du Colombier if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
509*5efba406SDavid du Colombier print("software cursor: allocmemimage fails\n");
510*5efba406SDavid du Colombier return;
511*5efba406SDavid du Colombier }
512*5efba406SDavid du Colombier
513*5efba406SDavid du Colombier memfillcolor(swmask, DOpaque);
514*5efba406SDavid du Colombier memfillcolor(swmask1, DOpaque);
515*5efba406SDavid du Colombier memfillcolor(swimg, DBlack);
516*5efba406SDavid du Colombier memfillcolor(swimg1, DBlack);
51793631029SDavid du Colombier }
51893631029SDavid du Colombier
519634d7e5aSDavid du Colombier /* called from main and possibly later from devdss to change resolution */
52093631029SDavid du Colombier void
screeninit(void)52193631029SDavid du Colombier screeninit(void)
52293631029SDavid du Colombier {
523634d7e5aSDavid du Colombier static int first = 1;
524634d7e5aSDavid du Colombier
525634d7e5aSDavid du Colombier if (first) {
52693631029SDavid du Colombier iprint("screeninit...");
527*5efba406SDavid du Colombier oscreen.settings = &settings[Res1280x1024];
528634d7e5aSDavid du Colombier
529634d7e5aSDavid du Colombier lcdstop();
530634d7e5aSDavid du Colombier if (framebuf)
531634d7e5aSDavid du Colombier free(framebuf);
53293631029SDavid du Colombier /* mode is 16*32 = 512 */
53393631029SDavid du Colombier framebuf = xspanalloc(sizeof *framebuf, 16*32, 0);
534634d7e5aSDavid du Colombier }
53593631029SDavid du Colombier
53693631029SDavid du Colombier lcdinit();
53793631029SDavid du Colombier lcdon(1);
538634d7e5aSDavid du Colombier if (first) {
539634d7e5aSDavid du Colombier memimageinit();
540634d7e5aSDavid du Colombier memdefont = getmemdefont();
54193631029SDavid du Colombier screentest();
542634d7e5aSDavid du Colombier }
54393631029SDavid du Colombier
54493631029SDavid du Colombier xgdata.ref = 1;
54593631029SDavid du Colombier xgdata.bdata = (uchar *)framebuf->pixel;
54693631029SDavid du Colombier
54793631029SDavid du Colombier gscreen = &xgscreen;
54893631029SDavid du Colombier gscreen->r = Rect(0, 0, Wid, Ht);
54993631029SDavid du Colombier gscreen->clipr = gscreen->r;
55093631029SDavid du Colombier /* width, in words, of a single scan line */
55193631029SDavid du Colombier gscreen->width = Wid * (Depth / BI2BY) / BY2WD;
55293631029SDavid du Colombier flushmemscreen(gscreen->r);
55393631029SDavid du Colombier
554*5efba406SDavid du Colombier blanktime = 3; /* minutes */
555*5efba406SDavid du Colombier
556634d7e5aSDavid du Colombier if (first) {
557634d7e5aSDavid du Colombier iprint("on: blue for 3 seconds...");
558634d7e5aSDavid du Colombier delay(3*1000);
55993631029SDavid du Colombier iprint("\n");
56093631029SDavid du Colombier
561bacfa46cSDavid du Colombier screenwin(); /* draw border & top orange bar */
56293631029SDavid du Colombier screenputs = omapscreenputs;
563634d7e5aSDavid du Colombier iprint("screen: frame buffer at %#p for %dx%d\n",
564*5efba406SDavid du Colombier framebuf, oscreen.settings->wid, oscreen.settings->ht);
565*5efba406SDavid du Colombier
566*5efba406SDavid du Colombier swenabled = 1;
567*5efba406SDavid du Colombier swcursorinit(); /* needs gscreen set */
568*5efba406SDavid du Colombier setcursor(&arrow);
569*5efba406SDavid du Colombier
570634d7e5aSDavid du Colombier first = 0;
571634d7e5aSDavid du Colombier }
57293631029SDavid du Colombier }
57393631029SDavid du Colombier
57493631029SDavid du Colombier /* flushmemscreen should change buffer? */
57593631029SDavid du Colombier void
flushmemscreen(Rectangle r)57693631029SDavid du Colombier flushmemscreen(Rectangle r)
57793631029SDavid du Colombier {
57893631029SDavid du Colombier ulong start, end;
57993631029SDavid du Colombier
58093631029SDavid du Colombier if (r.min.x < 0)
58193631029SDavid du Colombier r.min.x = 0;
58293631029SDavid du Colombier if (r.max.x > Wid)
58393631029SDavid du Colombier r.max.x = Wid;
58493631029SDavid du Colombier if (r.min.y < 0)
58593631029SDavid du Colombier r.min.y = 0;
58693631029SDavid du Colombier if (r.max.y > Ht)
58793631029SDavid du Colombier r.max.y = Ht;
58893631029SDavid du Colombier if (rectclip(&r, gscreen->r) == 0)
58993631029SDavid du Colombier return;
59093631029SDavid du Colombier start = (ulong)&framebuf->pixel[r.min.y*Wid + r.min.x];
59193631029SDavid du Colombier end = (ulong)&framebuf->pixel[(r.max.y - 1)*Wid + r.max.x -1];
59293631029SDavid du Colombier cachedwbse((ulong *)start, end - start);
59393631029SDavid du Colombier }
59493631029SDavid du Colombier
59593631029SDavid du Colombier /*
59693631029SDavid du Colombier * export screen to devdraw
59793631029SDavid du Colombier */
59893631029SDavid du Colombier uchar*
attachscreen(Rectangle * r,ulong * chan,int * d,int * width,int * softscreen)59993631029SDavid du Colombier attachscreen(Rectangle *r, ulong *chan, int *d, int *width, int *softscreen)
60093631029SDavid du Colombier {
60193631029SDavid du Colombier *r = gscreen->r;
60293631029SDavid du Colombier *d = gscreen->depth;
60393631029SDavid du Colombier *chan = gscreen->chan;
60493631029SDavid du Colombier *width = gscreen->width;
60593631029SDavid du Colombier *softscreen = (landscape == 0);
60693631029SDavid du Colombier return (uchar *)gscreen->data->bdata;
60793631029SDavid du Colombier }
60893631029SDavid du Colombier
60993631029SDavid du Colombier void
getcolor(ulong p,ulong * pr,ulong * pg,ulong * pb)61093631029SDavid du Colombier getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
61193631029SDavid du Colombier {
61293631029SDavid du Colombier USED(p, pr, pg, pb);
61393631029SDavid du Colombier }
61493631029SDavid du Colombier
61593631029SDavid du Colombier int
setcolor(ulong p,ulong r,ulong g,ulong b)61693631029SDavid du Colombier setcolor(ulong p, ulong r, ulong g, ulong b)
61793631029SDavid du Colombier {
61893631029SDavid du Colombier USED(p, r, g, b);
61993631029SDavid du Colombier return 0;
62093631029SDavid du Colombier }
62193631029SDavid du Colombier
62293631029SDavid du Colombier void
blankscreen(int blank)62393631029SDavid du Colombier blankscreen(int blank)
62493631029SDavid du Colombier {
62593631029SDavid du Colombier if (blank)
62693631029SDavid du Colombier lcdon(0);
62793631029SDavid du Colombier else {
62893631029SDavid du Colombier lcdinit();
62993631029SDavid du Colombier lcdon(1);
63093631029SDavid du Colombier }
63193631029SDavid du Colombier }
63293631029SDavid du Colombier
63393631029SDavid du Colombier static void
omapscreenputs(char * s,int n)63493631029SDavid du Colombier omapscreenputs(char *s, int n)
63593631029SDavid du Colombier {
63693631029SDavid du Colombier int i;
63793631029SDavid du Colombier Rune r;
63893631029SDavid du Colombier char buf[4];
63993631029SDavid du Colombier
64093631029SDavid du Colombier if (!islo()) {
64193631029SDavid du Colombier /* don't deadlock trying to print in interrupt */
64293631029SDavid du Colombier if (!canlock(&screenlock))
64393631029SDavid du Colombier return; /* discard s */
64493631029SDavid du Colombier } else
64593631029SDavid du Colombier lock(&screenlock);
64693631029SDavid du Colombier
64793631029SDavid du Colombier while (n > 0) {
64893631029SDavid du Colombier i = chartorune(&r, s);
64993631029SDavid du Colombier if (i == 0) {
65093631029SDavid du Colombier s++;
65193631029SDavid du Colombier --n;
65293631029SDavid du Colombier continue;
65393631029SDavid du Colombier }
65493631029SDavid du Colombier memmove(buf, s, i);
65593631029SDavid du Colombier buf[i] = 0;
65693631029SDavid du Colombier n -= i;
65793631029SDavid du Colombier s += i;
65893631029SDavid du Colombier screenputc(buf);
65993631029SDavid du Colombier }
66093631029SDavid du Colombier unlock(&screenlock);
66193631029SDavid du Colombier }
66293631029SDavid du Colombier
66393631029SDavid du Colombier static void
screenwin(void)66493631029SDavid du Colombier screenwin(void)
66593631029SDavid du Colombier {
66693631029SDavid du Colombier char *greet;
66793631029SDavid du Colombier Memimage *orange;
66893631029SDavid du Colombier Point p, q;
66993631029SDavid du Colombier Rectangle r;
67093631029SDavid du Colombier
67193631029SDavid du Colombier memsetchan(gscreen, RGB16);
67293631029SDavid du Colombier
67393631029SDavid du Colombier back = memwhite;
67493631029SDavid du Colombier conscol = memblack;
67593631029SDavid du Colombier
67693631029SDavid du Colombier orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
67793631029SDavid du Colombier orange->flags |= Frepl;
67893631029SDavid du Colombier orange->clipr = gscreen->r;
67993631029SDavid du Colombier orange->data->bdata[0] = 0x40; /* magic: colour? */
68093631029SDavid du Colombier orange->data->bdata[1] = 0xfd; /* magic: colour? */
68193631029SDavid du Colombier
68293631029SDavid du Colombier w = memdefont->info[' '].width;
68393631029SDavid du Colombier h = memdefont->height;
68493631029SDavid du Colombier
68593631029SDavid du Colombier r = insetrect(gscreen->r, 4);
68693631029SDavid du Colombier
68793631029SDavid du Colombier memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
68893631029SDavid du Colombier window = insetrect(r, 4);
68993631029SDavid du Colombier memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
69093631029SDavid du Colombier
69193631029SDavid du Colombier memimagedraw(gscreen, Rect(window.min.x, window.min.y,
69293631029SDavid du Colombier window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
69393631029SDavid du Colombier freememimage(orange);
69493631029SDavid du Colombier window = insetrect(window, 5);
69593631029SDavid du Colombier
69693631029SDavid du Colombier greet = " Plan 9 Console ";
69793631029SDavid du Colombier p = addpt(window.min, Pt(10, 0));
69893631029SDavid du Colombier q = memsubfontwidth(memdefont, greet);
69993631029SDavid du Colombier memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
70093631029SDavid du Colombier flushmemscreen(r);
70193631029SDavid du Colombier window.min.y += h + 6;
70293631029SDavid du Colombier curpos = window.min;
70393631029SDavid du Colombier window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
70493631029SDavid du Colombier }
70593631029SDavid du Colombier
70693631029SDavid du Colombier static void
scroll(void)70793631029SDavid du Colombier scroll(void)
70893631029SDavid du Colombier {
70993631029SDavid du Colombier int o;
71093631029SDavid du Colombier Point p;
71193631029SDavid du Colombier Rectangle r;
71293631029SDavid du Colombier
713634d7e5aSDavid du Colombier /* move window contents up Scroll text lines */
714634d7e5aSDavid du Colombier o = Scroll * h;
71593631029SDavid du Colombier r = Rpt(window.min, Pt(window.max.x, window.max.y - o));
71693631029SDavid du Colombier p = Pt(window.min.x, window.min.y + o);
71793631029SDavid du Colombier memimagedraw(gscreen, r, gscreen, p, nil, p, S);
71893631029SDavid du Colombier flushmemscreen(r);
71993631029SDavid du Colombier
720634d7e5aSDavid du Colombier /* clear the bottom Scroll text lines */
72193631029SDavid du Colombier r = Rpt(Pt(window.min.x, window.max.y - o), window.max);
72293631029SDavid du Colombier memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
72393631029SDavid du Colombier flushmemscreen(r);
72493631029SDavid du Colombier
72593631029SDavid du Colombier curpos.y -= o;
72693631029SDavid du Colombier }
72793631029SDavid du Colombier
72893631029SDavid du Colombier static void
screenputc(char * buf)72993631029SDavid du Colombier screenputc(char *buf)
73093631029SDavid du Colombier {
73193631029SDavid du Colombier int w;
73293631029SDavid du Colombier uint pos;
73393631029SDavid du Colombier Point p;
73493631029SDavid du Colombier Rectangle r;
73593631029SDavid du Colombier static int *xp;
73693631029SDavid du Colombier static int xbuf[256];
73793631029SDavid du Colombier
73893631029SDavid du Colombier if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
73993631029SDavid du Colombier xp = xbuf;
74093631029SDavid du Colombier
74193631029SDavid du Colombier switch (buf[0]) {
74293631029SDavid du Colombier case '\n':
74393631029SDavid du Colombier if (curpos.y + h >= window.max.y)
74493631029SDavid du Colombier scroll();
74593631029SDavid du Colombier curpos.y += h;
74693631029SDavid du Colombier screenputc("\r");
74793631029SDavid du Colombier break;
74893631029SDavid du Colombier case '\r':
74993631029SDavid du Colombier xp = xbuf;
75093631029SDavid du Colombier curpos.x = window.min.x;
75193631029SDavid du Colombier break;
75293631029SDavid du Colombier case '\t':
75393631029SDavid du Colombier p = memsubfontwidth(memdefont, " ");
75493631029SDavid du Colombier w = p.x;
75593631029SDavid du Colombier if (curpos.x >= window.max.x - Tabstop * w)
75693631029SDavid du Colombier screenputc("\n");
75793631029SDavid du Colombier
75893631029SDavid du Colombier pos = (curpos.x - window.min.x) / w;
75993631029SDavid du Colombier pos = Tabstop - pos % Tabstop;
76093631029SDavid du Colombier *xp++ = curpos.x;
76193631029SDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
76293631029SDavid du Colombier memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
76393631029SDavid du Colombier flushmemscreen(r);
76493631029SDavid du Colombier curpos.x += pos * w;
76593631029SDavid du Colombier break;
76693631029SDavid du Colombier case '\b':
76793631029SDavid du Colombier if (xp <= xbuf)
76893631029SDavid du Colombier break;
76993631029SDavid du Colombier xp--;
77093631029SDavid du Colombier r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
77193631029SDavid du Colombier memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
77293631029SDavid du Colombier flushmemscreen(r);
77393631029SDavid du Colombier curpos.x = *xp;
77493631029SDavid du Colombier break;
77593631029SDavid du Colombier case '\0':
77693631029SDavid du Colombier break;
77793631029SDavid du Colombier default:
77893631029SDavid du Colombier p = memsubfontwidth(memdefont, buf);
77993631029SDavid du Colombier w = p.x;
78093631029SDavid du Colombier
78193631029SDavid du Colombier if (curpos.x >= window.max.x - w)
78293631029SDavid du Colombier screenputc("\n");
78393631029SDavid du Colombier
78493631029SDavid du Colombier *xp++ = curpos.x;
78593631029SDavid du Colombier r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
78693631029SDavid du Colombier memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
78793631029SDavid du Colombier memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
78893631029SDavid du Colombier flushmemscreen(r);
78993631029SDavid du Colombier curpos.x += w;
79093631029SDavid du Colombier }
79193631029SDavid du Colombier }
792