123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- #include "u.h"
- #include "mem.h"
- #include "../port/lib.h"
- #include "dat.h"
- #include "draw.h"
- #include "fns.h"
- #include "io.h"
- #include <memdraw.h>
- #include "screen.h"
- #define DPRINT if(1)iprint
- enum {
- /* lccr0 */
- EnableCtlr = 1<<0, /* controller enable */
- IsColour = 0<<1,
- IsMono = 1<<1,
- SinglePanel = 0<<2,
- DualPanel = 1<<2,
- DisableDone = 1<<3,
- DisableBAU = 1<<4,
- DisableErr = 1<<5,
- PassivePanel = 0<<7,
- ActivePanel = 1<<7,
- BigEndian = 1<<8,
- DoublePixel = 1<<9,
- /* 19:12 is palette dma delay */
- /* lcsr */
- CtlrReady = 1<<0,
- /* lccr3 */
- VsyncLow = 1<<20,
- HsyncLow = 1<<21,
- PixelClockLow = 1<<22,
- OELow = 1<<23,
- };
- typedef struct {
- Vdisplay;
- LCDparam;
- ushort* palette;
- uchar* upper;
- uchar* lower;
- } LCDdisplay;
- static LCDdisplay *vd; // current active display
- void
- lcd_setcolor(ulong p, ulong r, ulong g, ulong b)
- {
- if(vd->pbs == 0 && p > 15 ||
- vd->pbs == 1 && p > 255 ||
- vd->pbs == 2)
- return;
- vd->palette[p] = (vd->pbs<<12) |
- ((r>>(32-4))<<8) |
- ((g>>(32-4))<<4) |
- (b>>(32-4));
- }
- static void
- disablelcd(void)
- {
- LcdReg *lcd = LCDREG;
- int i;
- /* if LCD enabled, turn off and wait for current frame to end */
- if(lcd->lccr0 & EnableCtlr) {
- lcd->lccr0 &= ~EnableCtlr;
- for(i=0; i < 50 && !(lcd->lcsr & CtlrReady); i++)
- delay(5);
- }
- }
- static void
- setlcdmode(LCDdisplay *vd)
- {
- LCDmode *p;
- int ppf, pclk, clockdiv;
- ulong v, c;
- LcdReg *lcd = LCDREG;
- GpioReg *gpio = GPIOREG;
- p = (LCDmode*)&vd->Vmode;
- ppf = ((((p->x+p->sol_wait+p->eol_wait) *
- (p->mono ? 1 : 3)) >> (3-p->mono)) +
- p->hsync_wid) *
- (p->y/(p->dual+1)+p->vsync_hgt+
- p->sof_wait+p->eof_wait);
- pclk = ppf*p->hz;
- clockdiv = ((m->cpuhz/pclk) >> 1)-2;
- DPRINT(" oclockdiv=%d\n", clockdiv);
- clockdiv=0x10;
- disablelcd();
- lcd->lccr0 = 0; /* reset it */
- DPRINT(" pclk=%d clockdiv=%d\n", pclk, clockdiv);
- lcd->lccr3 = (clockdiv << 0) |
- (p->acbias_lines << 8) |
- (p->lines_per_int << 16) |
- VsyncLow | HsyncLow; /* vsync active low, hsync active low */
- lcd->lccr2 = (((p->y/(p->dual+1))-1) << 0) |
- (p->vsync_hgt << 10) |
- (p->eof_wait << 16) |
- (p->sof_wait << 24);
- lcd->lccr1 = ((p->x-16) << 0) |
- (p->hsync_wid << 10) |
- (p->eol_wait << 16) |
- (p->sol_wait << 24);
- // enable LCD controller, CODEC, and lower 4/8 data bits (for tft/dual)
- v = p->obits < 12? 0: p->obits < 16? 0x3c: 0x3fc;
- c = p->obits == 12? 0x3c0: 0;
- gpio->gafr |= v;
- gpio->gpdr |= v | c;
- gpio->gpcr = c;
- lcd->dbar1 = PADDR(vd->palette);
- if(vd->dual)
- lcd->dbar2 = PADDR(vd->lower);
- // Enable LCD
- lcd->lccr0 = EnableCtlr | (p->mono?IsMono:IsColour)
- | (p->palette_delay << 12)
- | (p->dual ? DualPanel : SinglePanel)
- | (p->active? ActivePanel: PassivePanel)
- | DisableDone | DisableBAU | DisableErr;
- // recalculate actual HZ
- pclk = (m->cpuhz/(clockdiv+2)) >> 1;
- p->hz = pclk/ppf;
- archlcdenable(1);
- iprint("lccr0=%8.8lux lccr1=%8.8lux lccr2=%8.8lux lccr3=%8.8lux\n", lcd->lccr0, lcd->lccr1, lcd->lccr2, lcd->lccr3);
- }
- static LCDdisplay main_display; /* TO DO: limits us to a single display */
- Vdisplay*
- lcd_init(LCDmode *p)
- {
- int palsize;
- int fbsize;
- vd = &main_display;
- vd->Vmode = *p;
- vd->LCDparam = *p;
- DPRINT("%dx%dx%d: hz=%d\n", vd->x, vd->y, vd->depth, vd->hz); /* */
- palsize = vd->pbs==1? 256 : 16;
- fbsize = palsize*2+(((vd->x*vd->y) * vd->depth) >> 3);
- if((vd->palette = xspanalloc(fbsize+CACHELINESZ+512, CACHELINESZ, 0)) == nil) /* at least 16-byte alignment */
- panic("no vidmem, no party...");
- vd->palette[0] = (vd->pbs<<12);
- vd->palette = minicached(vd->palette);
- vd->upper = (uchar*)(vd->palette + palsize);
- vd->bwid = (vd->x << vd->pbs) >> 1;
- vd->lower = vd->upper+((vd->bwid*vd->y) >> 1);
- vd->fb = vd->upper;
- DPRINT(" fbsize=%d p=%p u=%p l=%p\n", fbsize, vd->palette, vd->upper, vd->lower); /* */
- setlcdmode(vd);
- return vd;
- }
- void
- lcd_flush(void)
- {
- if(conf.useminicache)
- minidcflush();
- else
- dcflushall(); /* need more precise addresses */
- }
- void
- blankscreen(int blank)
- {
- if (blank) {
- disablelcd();
- archlcdenable(0);
- } else {
- archlcdenable(1);
- setlcdmode(&main_display);
- }
- }
|