800 lines · 16.3 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * ti omap35 display subsystem (dss) * * can handle 2ⁿ bits per pixel for 0 < n ≤ 4, and 12 and 24 bits. * can handle	1024×768 at 60 Hz with pixel clock of 63.5 MHz *		1280×800 at 59.91 Hz with pixel clock of 71 MHz *		1400×1050 lcd at 50 MHz with pixel clock of 75 MHz * has 256 24-bit entries in RGB palette */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "../port/error.h" #define	Image	IMAGE#include <draw.h>#include <memdraw.h>#include <cursor.h>#include "screen.h"// #include "gamma.h" enum {	Tabstop	= 4,		/* should be 8 */	Scroll	= 8,		/* lines to scroll at one time */	/*	 * screen settings for Wid and Ht, should a bit more dynamic?	 * http://www.epanorama.net/faq/vga2rgb/calc.html	 * used to calculate settings.	 */ //	Hbp     = (248-1) << 20,//	Hfp     = (48-1) << 8,//	Hsw     = 112-1, //	Vbp     = 38 << 20,//	Vfp     = 1 << 8,//	Vsw     = 3, 	Tft	= 0x60, 	Loadmode = 2 << 1,	Fifosize = 0x400, 	/* dispc sysconfig */	Midlemode	= 2 << 12,	Sidlemode	= 2 << 3,	EnableWakeup	= 1 << 2,	Autoidle	= 1 << 0, 	/* dispc pool_freq */	Ipc		= 1 << 14,	Ihs		= 1 << 13,	Ivs		= 1 << 12,	Acb		= 0x28, 	/* gfx attribs */	Burstsize	= 2 << 6,	Format		= 6 << 1,	Gfxenable	= 1 << 0, 	/* dispc control */	Gpout1		= 1 << 16,	Gpout0		= 1 << 15,	Tftdata		= 3 << 8,	Digital		= 1 << 6,	Lcd		= 1 << 5,	Stntft		= 1 << 3,	Digitalen	= 1 << 1,//	Lcden		= 1 << 0,	/* unused */}; typedef struct Dispcregs Dispc;typedef struct Dssregs Dss;typedef struct Ioregs Ioregs; struct Ioregs {				/* common registers, 68 (0x44) bytes */	ulong 	rev;	uchar	_pad0[0x10-0x4];	ulong	sysconf;	ulong	sysstat;	ulong	irqstat1; 	/* Dispc only regs */	ulong	irqen1;	ulong	wkupen;	ulong	_pad1;	ulong	irqsts2;	ulong	irqen2;	ulong	_pad2[4]; 	ulong	ctrl;}; struct Dssregs {			/* display subsys at 0x48050000 */	Ioregs;	ulong	sdicrtl;	ulong	pllcrtl;	uchar	_pad3[0x5c-0x4c];	ulong	sdistat;}; struct Dispcregs {			/* display ctlr at 0x48050400 */	Ioregs;	ulong	config;	ulong	_pad3;	ulong 	defaultcolor[2];	ulong	transcolor[2];	ulong	linestat;	ulong	linenum;	ulong	timing_h;	ulong	timing_v;	ulong	pol_req;	ulong	divisor;	ulong	alpha;	ulong	digsize;	ulong	lcdsize; 	ulong	base[2];	/* should allocate both to avoid dithering */	ulong	pos;	ulong	size;	ulong	_pad4[4];	ulong	attrib;	ulong	fifothr;	ulong	fifosize;	ulong	rowinc;	ulong	pixelinc;	ulong	winskip;	ulong	palette;		/* gfx_table_ba */	uchar	_pad5[0x5d4 - 0x4bc]; 	ulong	datacycle[3];	uchar	_pad5[0x620 - 0x5e0]; 	ulong	cprcoefr;	ulong	cprcoefg;	ulong	cprcoefb;	ulong	preload;}; int	drawdebug;Point	ZP = {0, 0};Cursor	arrow = {	{ -1, -1 },	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,	},	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,	},}; OScreen oscreen;Settings settings[] = {[Res800x600]   {  800,  600, 60, RGB16,  40000,	 88, 40, 128,	23, 1, 5, },[Res1024x768]  { 1024,  768, 60, RGB16,  65000,	160, 24, 136,	29, 3, 7, },[Res1280x1024] { 1280, 1024, 60, RGB16, 108000,	248, 48, 112,	38, 1, 4, },[Res1400x1050] { 1400, 1050, 50, RGB16, 108000, 248, 48, 112,	38, 1, 4, }, // TODO};Omap3fb *framebuf;Memimage *gscreen; static Memdata xgdata; static Memimage xgscreen ={	{ 0, 0, Wid, Ht },	/* r */	{ 0, 0, Wid, Ht },	/* clipr */	Depth,			/* depth */	3,			/* nchan */	RGB16,			/* chan */	nil,			/* cmap */	&xgdata,		/* data */	0,			/* zero */	Wid*(Depth/BI2BY)/BY2WD, /* width in words of a single scan line */	0,			/* layer */	0,			/* flags */}; static Memimage *conscol;static Memimage *back; static Memsubfont *memdefont; static Lock screenlock; static Point	curpos;static int	h, w;static int	landscape = 0;	/* screen orientation, default is 0: portrait */static ushort	*vscreen;	/* virtual screen */static Rectangle window; static Dispc *dispc = (Dispc *)PHYSDISPC;static Dss *dss	= (Dss *)PHYSDSS; static	void	omapscreenputs(char *s, int n);static	ulong	rep(ulong, int);static	void	screenputc(char *buf);static	void	screenwin(void); /* * Software cursor.  */int	swvisible;	/* is the cursor visible? */int	swenabled;	/* is the cursor supposed to be on the screen? */Memimage*	swback;	/* screen under cursor */Memimage*	swimg;	/* cursor image */Memimage*	swmask;	/* cursor mask */Memimage*	swimg1;Memimage*	swmask1; Point	swoffset;Rectangle	swrect;	/* screen rectangle in swback */Point	swpt;	/* desired cursor location */Point	swvispt;	/* actual cursor location */int	swvers;	/* incremented each time cursor image changes */int	swvisvers;	/* the version on the screen */ static voidlcdoff(void){	dispc->ctrl &= ~1;		/* disable the lcd */	coherence(); 	dispc->irqstat1 |= 1;		/* set framedone */	coherence(); 	/* the lcd never comes ready, so don't bother with this */#ifdef notdef	/* spin until the frame is complete, but not forever */	for(cnt = 50; !(dispc->irqstat1 & 1) && cnt-- > 0; )		delay(10);#endif	delay(20);			/* worst case for 1 frame, 50Hz */} static voiddssstart(void){	/* should reset the dss system */	dss->sysconf |= 1;	coherence();} /* see spruf98i §15.6.7.4.2 */static voidconfigdispc(void){	Settings *sp; 	sp = oscreen.settings;	dss->ctrl &= 0x78;		/* choose dss clock */	dispc->sysconf = Midlemode | Sidlemode | EnableWakeup | Autoidle;	dispc->config = Loadmode;	coherence(); 	/* pll */	dispc->defaultcolor[0] = 0;	/* set background color to black? */	dispc->defaultcolor[1] = 0;	dispc->transcolor[0] = 0;	/* set transparency to full */	dispc->transcolor[1] = 0; 	dispc->timing_h = (sp->hbp-1) << 20 | (sp->hfp-1) << 8 |			(sp->hsw-1);	dispc->timing_v = sp->vbp << 20 | sp->vfp << 8 |			(sp->vsw-1); 	dispc->pol_req = Ipc | Ihs | Ivs | Acb;	dispc->divisor = 1 << 16 | HOWMANY(432000, sp->pixelclock); 	dispc->lcdsize = (sp->ht - 1) << 16 | (sp->wid - 1);	coherence(); 	dispc->base[0] = PADDR(framebuf->pixel);	dispc->base[1] = PADDR(framebuf->pixel); 	dispc->pos = 0;			/* place screen in the left corner */	/* use the whole screen */	dispc->size = (sp->ht - 1) << 16 | (sp->wid - 1); 	/* what mode does plan 9 use for fb? */	dispc->attrib = Burstsize | Format | Gfxenable; 	dispc->preload = Tft;	dispc->fifosize = Fifosize;	/* 1008 is max for our Burstsize */	dispc->fifothr = (Fifosize - 1) << 16 | (1008 - 1); 	/* 1 byte is one pixel (not true, we use 2 bytes per pixel) */	dispc->rowinc = 1;	dispc->pixelinc = 1;	dispc->winskip = 0;		/* don't skip anything */	coherence(); 	// dispc->palette = PADDR(framebuf->palette);} static voidlcdon(int enable){	dispc->ctrl = Gpout1 | Gpout0 | Tftdata | Digital | Lcd | Stntft |		Digitalen | enable;	coherence();	delay(10);} static voidlcdstop(void){	configscreengpio();	screenclockson(); 	lcdoff();} static voidlcdinit(void){	lcdstop(); 	dssstart();	configdispc();} /* Paint the image data with blue pixels */voidscreentest(void){	int i; 	for (i = nelem(framebuf->pixel) - 1; i >= 0; i--)		framebuf->pixel[i] = 0x1f;			/* blue *///	memset(framebuf->pixel, ~0, sizeof framebuf->pixel);	/* white */} voidscreenpower(int on){	blankscreen(on == 0);} /* * called with drawlock locked for us, most of the time. * kernel prints at inopportune times might mean we don't * hold the lock, but memimagedraw is now reentrant so * that should be okay: worst case we get cursor droppings. */voidswcursorhide(void){	if(swvisible == 0)		return;	if(swback == nil)		return;	swvisible = 0;	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);	flushmemscreen(swrect);} voidswcursoravoid(Rectangle r){	if(swvisible && rectXrect(r, swrect))		swcursorhide();} voidswcursordraw(void){	if(swvisible)		return;	if(swenabled == 0)		return;	if(swback == nil || swimg1 == nil || swmask1 == nil)		return;//	assert(!canqlock(&drawlock));		// assertion fails on omap	swvispt = swpt;	swvisvers = swvers;	swrect = rectaddpt(Rect(0,0,16,16), swvispt);	memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);	flushmemscreen(swrect);	swvisible = 1;} intcursoron(int dolock){	if (dolock)		lock(&oscreen);	cursoroff(0);	swcursordraw();	if (dolock)		unlock(&oscreen);	return 0;} voidcursoroff(int dolock){	if (dolock)		lock(&oscreen);	swcursorhide();	if (dolock)		unlock(&oscreen);} voidswload(Cursor *curs){	uchar *ip, *mp;	int i, j, set, clr; 	if(!swimg || !swmask || !swimg1 || !swmask1)		return;	/*	 * Build cursor image and mask.	 * Image is just the usual cursor image	 * but mask is a transparent alpha mask.	 * 	 * The 16x16x8 memimages do not have	 * padding at the end of their scan lines.	 */	ip = byteaddr(swimg, ZP);	mp = byteaddr(swmask, ZP);	for(i=0; i<32; i++){		set = curs->set[i];		clr = curs->clr[i];		for(j=0x80; j; j>>=1){			*ip++ = set&j ? 0x00 : 0xFF;			*mp++ = (clr|set)&j ? 0xFF : 0x00;		}	}	swoffset = curs->offset;	swvers++;	memimagedraw(swimg1,  swimg1->r,  swimg,  ZP, memopaque, ZP, S);	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);} /* called from devmouse */voidsetcursor(Cursor* curs){	cursoroff(1);	oscreen.Cursor = *curs;	swload(curs);	cursoron(1);} intswmove(Point p){	swpt = addpt(p, swoffset);	return 0;} voidswcursorclock(void){	int x; 	if(!swenabled)		return;	swmove(mousexy());	if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)		return; 	x = splhi();	if(swenabled)	if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)	if(canqlock(&drawlock)){		swcursorhide();		swcursordraw();		qunlock(&drawlock);	}	splx(x);} voidswcursorinit(void){	static int init; 	if(!init){

Lines 1–500 of 800.