shithub: riscv

Download patch

ref: 15590e39c6be92d8a9ecb2f00b015dbb9a3dc0b0
parent: cf76346b37ddbd54b8d1fe5580ab813a8165392b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Jan 9 17:23:25 EST 2015

igfx: implement hardware cursor

this can even be used with the vesa driver, just
enable the cursor after mode switch like:

echo hwgc igfxhwgc >/dev/vgactl

--- a/sys/src/9/pc/pccpuf
+++ b/sys/src/9/pc/pccpuf
@@ -113,7 +113,7 @@
 	vgageode	+cur
 	vgahiqvideo	+cur
 	vgai81x		+cur
-	vgaigfx
+	vgaigfx		+cur
 	vgamach64xx	+cur
 	vgamga2164w	+cur
 	vgamga4xx	+cur
--- a/sys/src/9/pc/pcf
+++ b/sys/src/9/pc/pcf
@@ -114,7 +114,7 @@
 	vgageode	+cur
 	vgahiqvideo	+cur
 	vgai81x		+cur
-	vgaigfx
+	vgaigfx		+cur
 	vgamach64xx	+cur
 	vgamga2164w	+cur
 	vgamga4xx	+cur
--- a/sys/src/9/pc/vgaigfx.c
+++ b/sys/src/9/pc/vgaigfx.c
@@ -28,11 +28,124 @@
 	addvgaseg("igfxmmio", p->mem[0].bar&~0x0F, p->mem[1].size);
 	if(scr->paddr == 0)
 		vgalinearpci(scr);
-	if(scr->apsize)
+	if(scr->apsize){
 		addvgaseg("igfxscreen", scr->paddr, scr->apsize);
+		scr->storage = (scr->apsize - 64*64*4) & ~(BY2PG-1);
+		if(scr->storage > 0x1000000)
+			scr->storage = 0x1000000;
+	}
 }
 
 VGAdev vgaigfxdev = {
 	"igfx",
 	igfxenable,
+};
+
+static void
+igfxcurload(VGAscr* scr, Cursor* curs)
+{
+	uchar set, clr;
+	u32int *p;
+	int i, j;
+
+	p = (u32int*)((uchar*)scr->vaddr + scr->storage);
+	memset(p, 0, 64*64*4);
+	for(i=0;i<32;i++) {
+		set = curs->set[i];
+		clr = curs->clr[i];
+		for(j=0x80; j; j>>=1){
+			if((set|clr)&j)
+				*p++ = (0xFF<<24) | (set&j ? 0x000000 : 0xFFFFFF);
+			else
+				*p++ = 0;
+		}
+		if(i & 1)
+			p += 64-16;
+	}
+	scr->offset = curs->offset;
+}
+
+enum {
+	CURCTL = 0,
+	CURBASE,
+	CURPOS,
+
+	NPIPE = 3,
+};
+
+static u32int*
+igfxcurregs(VGAscr* scr, int pipe)
+{
+	u32int o;
+
+	if(scr->mmio == nil || scr->storage == 0)
+		return nil;
+	o = pipe*0x1000;
+	/* check PIPExCONF if enabled */
+	if((scr->mmio[(0x70008 | o)/4] & (1<<31)) == 0)
+		return nil;
+	if(scr->pci->did == 0x2a42){	/* G45 */
+		if(pipe > 1)
+			return nil;
+		o = pipe*0x40;
+	}
+	return (u32int*)((uchar*)scr->mmio + (0x70080 + o));
+}
+
+static int
+igfxcurmove(VGAscr* scr, Point p)
+{
+	int i, x, y;
+	u32int *r;
+
+	for(i=0; i<NPIPE; i++){
+		if((r = igfxcurregs(scr, i)) != nil){
+			x = p.x + scr->offset.x;
+			if(x < 0) x = -x | 0x8000;
+			y = p.y + scr->offset.y;
+			if(y < 0) y = -y | 0x8000;
+			r[CURPOS] = (y << 16) | x;
+		}
+	}
+	return 0;
+}
+
+static void
+igfxcurenable(VGAscr* scr)
+{
+	u32int *r;
+	int i;
+
+	igfxenable(scr);
+	igfxcurload(scr, &arrow);
+	igfxcurmove(scr, ZP);
+
+	for(i=0; i<NPIPE; i++){
+		if((r = igfxcurregs(scr, i)) != nil){
+			r[CURCTL] = (r[CURCTL] & ~(3<<28 | 1<<5)) | (i<<28) | 7;
+			r[CURBASE] = scr->storage;
+		}
+	}
+}
+
+static void
+igfxcurdisable(VGAscr* scr)
+{
+	u32int *r;
+	int i;
+
+	for(i=0; i<NPIPE; i++){
+		if((r = igfxcurregs(scr, i)) != nil){
+			r[CURCTL] &= ~(1<<5 | 7);
+			r[CURBASE] = 0;
+		}
+	}
+}
+
+VGAcur vgaigfxcur = {
+	"igfxhwgc",
+	igfxcurenable,
+	igfxcurdisable,
+	igfxcurload,
+	igfxcurmove,
 };
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -112,6 +112,7 @@
 #	vgageode	+cur
 #	vgahiqvideo	+cur
 #	vgai81x		+cur
+	vgaigfx		+cur
 #	vgamach64xx	+cur
 #	vgamga2164w	+cur
 #	vgamga4xx	+cur
@@ -124,7 +125,6 @@
 #	vgatvp3020	=cur
 #	vgatvp3026	=cur
 	vgavesa
-	vgaigfx
 #	vgavmware	+cur
 
 ip
--- a/sys/src/cmd/aux/vga/data.c
+++ b/sys/src/cmd/aux/vga/data.c
@@ -41,6 +41,8 @@
 	&ics2494,				/* clock */
 	&ics2494a,				/* clock */
 	&ics534x,				/* gendac */
+	&igfx,					/* ctlr */
+	&igfxhwgc,				/* hwgc */
 	&mach32,				/* ctlr */
 	&mach64,				/* ctlr */
 	&mach64xx,				/* ctlr */
@@ -87,7 +89,6 @@
 	&w30c516,				/* ctlr */
 	&mga4xx,
 	&mga4xxhwgc,
-	&igfx,					/* ctlr */
 	0,
 };
 
--- a/sys/src/cmd/aux/vga/igfx.c
+++ b/sys/src/cmd/aux/vga/igfx.c
@@ -11,6 +11,7 @@
 typedef struct Dp Dp;
 typedef struct Fdi Fdi;
 typedef struct Pfit Pfit;
+typedef struct Curs Curs;
 typedef struct Plane Plane;
 typedef struct Trans Trans;
 typedef struct Pipe Pipe;
@@ -93,6 +94,12 @@
 	Reg	tileoff;	/* DSPxTILEOFF */
 };
 
+struct Curs {
+	Reg	cntr;
+	Reg	base;
+	Reg	pos;
+};
+
 struct Pipe {
 	Trans;
 
@@ -101,7 +108,7 @@
 	Fdi	fdi[1];		/* fdi/dp transcoder */
 
 	Plane	dsp[1];		/* display plane */
-	Plane	cur[1];		/* cursor plane */
+	Curs	cur[1];		/* hardware cursor */
 
 	Pfit	*pfit;		/* selected panel fitter */
 };
@@ -266,11 +273,13 @@
 	switch(igfx->type){
 	case TypeIVB:
 		p->cur->cntr	= snarfreg(igfx, 0x70080 | x*0x1000);
-		p->cur->surf	= snarfreg(igfx, 0x70084 | x*0x1000);
+		p->cur->base	= snarfreg(igfx, 0x70084 | x*0x1000);
+		p->cur->pos	= snarfreg(igfx, 0x70088 | x*0x1000);
 		break;
 	case TypeG45:
 		p->cur->cntr	= snarfreg(igfx, 0x70080 | x*0x40);
-		p->cur->surf	= snarfreg(igfx, 0x70084 | x*0x40);
+		p->cur->base	= snarfreg(igfx, 0x70084 | x*0x40);
+		p->cur->pos	= snarfreg(igfx, 0x7008C | x*0x40);
 		break;
 	}
 }
@@ -734,8 +743,9 @@
 	p->dsp->tileoff.v = 0;
 
 	/* cursor plane off */
-	p->cur->cntr.v = 0;
-	p->cur->surf.v = 0;
+	p->cur->cntr.v = x<<28;
+	p->cur->pos.v = 0;
+	p->cur->base.v = 0;
 
 	if(initdpll(igfx, x, m->frequency, islvds, 0) < 0)
 		error("%s: frequency %d out of range\n", ctlr->name, m->frequency);
@@ -841,8 +851,10 @@
 	loadreg(igfx, p->dsp->tileoff);
 	loadreg(igfx, p->dsp->surf);	/* arm */
 
+	/* program cursor */
 	loadreg(igfx, p->cur->cntr);
-	loadreg(igfx, p->cur->surf);	/* arm */
+	loadreg(igfx, p->cur->pos);
+	loadreg(igfx, p->cur->base);	/* arm */
 
 	if(0){
 		/* enable fdi */
@@ -897,8 +909,9 @@
 	/* planes off */
 	csr(igfx, p->dsp->cntr.a, 1<<31, 0);
 	csr(igfx, p->dsp->surf.a, ~0, 0);	/* arm */
-	csr(igfx, p->cur->cntr.a, 1<<31, 0);
-	csr(igfx, p->cur->surf.a, ~0, 0);	/* arm */
+	/* cursor off */
+	csr(igfx, p->cur->cntr.a, 1<<5 | 7, 0);
+	csr(igfx, p->cur->base.a, ~0, 0);	/* arm */
 
 	/* disable cpu pipe */
 	disabletrans(igfx, p);
@@ -1088,7 +1101,8 @@
 
 	snprint(name, sizeof(name), "%s cur %c", igfx->ctlr->name, 'a'+x);
 	dumpreg(name, "cntr", p->cur->cntr);
-	dumpreg(name, "surf", p->cur->surf);
+	dumpreg(name, "base", p->cur->base);
+	dumpreg(name, "pos", p->cur->pos);
 }
 
 static void
@@ -1118,25 +1132,25 @@
 	dumpreg(ctlr->name, "ssc4params", igfx->ssc4params);
 
 	for(x=0; x<nelem(igfx->dp); x++){
-		snprint(name, sizeof(name), "dp %c ctl", 'a'+x);
-		dumpreg(ctlr->name, name, igfx->dp[x].ctl);
+		snprint(name, sizeof(name), "%s dp %c", ctlr->name, 'a'+x);
+		dumpreg(name, "ctl", igfx->dp[x].ctl);
 	}
 	for(x=0; x<nelem(igfx->hdmi); x++){
-		snprint(name, sizeof(name), "hdmi %c ctl ", 'a'+x);
-		dumpreg(ctlr->name, name, igfx->hdmi[x].ctl);
+		snprint(name, sizeof(name), "%s hdmi %c", ctlr->name, 'a'+x);
+		dumpreg(name, "ctl", igfx->hdmi[x].ctl);
 	}
 
 	for(x=0; x<nelem(igfx->pfit); x++){
-		snprint(name, sizeof(name), "pfit %c ctrl", 'a'+x);
-		dumpreg(ctlr->name, name, igfx->pfit[x].ctrl);
-		snprint(name, sizeof(name), "pfit %c winpos", 'a'+x);
-		dumpreg(ctlr->name, name, igfx->pfit[x].winpos);
-		snprint(name, sizeof(name), "pfit %c winsize", 'a'+x);
-		dumpreg(ctlr->name, name, igfx->pfit[x].winsize);
-		snprint(name, sizeof(name), "pfit %c pwrgate", 'a'+x);
-		dumpreg(ctlr->name, name, igfx->pfit[x].pwrgate);
+		snprint(name, sizeof(name), "%s pfit %c", ctlr->name, 'a'+x);
+		dumpreg(name, "ctrl", igfx->pfit[x].ctrl);
+		dumpreg(name, "winpos", igfx->pfit[x].winpos);
+		dumpreg(name, "winsize", igfx->pfit[x].winsize);
+		dumpreg(name, "pwrgate", igfx->pfit[x].pwrgate);
 	}
 
+	dumpreg(ctlr->name, "ppcontrol", igfx->ppcontrol);
+	dumpreg(ctlr->name, "ppstatus", igfx->ppstatus);
+
 	dumpreg(ctlr->name, "adpa", igfx->adpa);
 	dumpreg(ctlr->name, "lvds", igfx->lvds);
 	dumpreg(ctlr->name, "sdvob", igfx->sdvob);
@@ -1152,4 +1166,8 @@
 	init,			/* init */
 	load,			/* load */
 	dump,			/* dump */
+};
+
+Ctlr igfxhwgc = {
+	"igfxhwgc",
 };
--- a/sys/src/cmd/aux/vga/vga.h
+++ b/sys/src/cmd/aux/vga/vga.h
@@ -311,6 +311,7 @@
 
 /* igfx.c */
 extern Ctlr igfx;
+extern Ctlr igfxhwgc;
 
 /* mach32.c */
 extern Ctlr mach32;