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;