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
This commit is contained in:
parent
cf76346b37
commit
15590e39c6
7 changed files with 159 additions and 26 deletions
|
@ -113,7 +113,7 @@ misc
|
|||
vgageode +cur
|
||||
vgahiqvideo +cur
|
||||
vgai81x +cur
|
||||
vgaigfx
|
||||
vgaigfx +cur
|
||||
vgamach64xx +cur
|
||||
vgamga2164w +cur
|
||||
vgamga4xx +cur
|
||||
|
|
|
@ -114,7 +114,7 @@ misc
|
|||
vgageode +cur
|
||||
vgahiqvideo +cur
|
||||
vgai81x +cur
|
||||
vgaigfx
|
||||
vgaigfx +cur
|
||||
vgamach64xx +cur
|
||||
vgamga2164w +cur
|
||||
vgamga4xx +cur
|
||||
|
|
|
@ -28,11 +28,124 @@ igfxenable(VGAscr* scr)
|
|||
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,
|
||||
};
|
||||
|
|
|
@ -112,6 +112,7 @@ misc
|
|||
# vgageode +cur
|
||||
# vgahiqvideo +cur
|
||||
# vgai81x +cur
|
||||
vgaigfx +cur
|
||||
# vgamach64xx +cur
|
||||
# vgamga2164w +cur
|
||||
# vgamga4xx +cur
|
||||
|
@ -124,7 +125,6 @@ misc
|
|||
# vgatvp3020 =cur
|
||||
# vgatvp3026 =cur
|
||||
vgavesa
|
||||
vgaigfx
|
||||
# vgavmware +cur
|
||||
|
||||
ip
|
||||
|
|
|
@ -41,6 +41,8 @@ Ctlr* ctlrs[] = {
|
|||
&ics2494, /* clock */
|
||||
&ics2494a, /* clock */
|
||||
&ics534x, /* gendac */
|
||||
&igfx, /* ctlr */
|
||||
&igfxhwgc, /* hwgc */
|
||||
&mach32, /* ctlr */
|
||||
&mach64, /* ctlr */
|
||||
&mach64xx, /* ctlr */
|
||||
|
@ -87,7 +89,6 @@ Ctlr* ctlrs[] = {
|
|||
&w30c516, /* ctlr */
|
||||
&mga4xx,
|
||||
&mga4xxhwgc,
|
||||
&igfx, /* ctlr */
|
||||
0,
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ typedef struct Hdmi Hdmi;
|
|||
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 @@ struct Plane {
|
|||
Reg tileoff; /* DSPxTILEOFF */
|
||||
};
|
||||
|
||||
struct Curs {
|
||||
Reg cntr;
|
||||
Reg base;
|
||||
Reg pos;
|
||||
};
|
||||
|
||||
struct Pipe {
|
||||
Trans;
|
||||
|
||||
|
@ -101,7 +108,7 @@ struct Pipe {
|
|||
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 @@ snarfpipe(Igfx *igfx, int x)
|
|||
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 @@ init(Vga* vga, Ctlr* ctlr)
|
|||
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 @@ enablepipe(Igfx *igfx, int x)
|
|||
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 @@ disablepipe(Igfx *igfx, int x)
|
|||
/* 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 @@ dumppipe(Igfx *igfx, int x)
|
|||
|
||||
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 @@ dump(Vga* vga, Ctlr* ctlr)
|
|||
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);
|
||||
|
@ -1153,3 +1167,7 @@ Ctlr igfx = {
|
|||
load, /* load */
|
||||
dump, /* dump */
|
||||
};
|
||||
|
||||
Ctlr igfxhwgc = {
|
||||
"igfxhwgc",
|
||||
};
|
||||
|
|
|
@ -311,6 +311,7 @@ extern Ctlr geodehwgc;
|
|||
|
||||
/* igfx.c */
|
||||
extern Ctlr igfx;
|
||||
extern Ctlr igfxhwgc;
|
||||
|
||||
/* mach32.c */
|
||||
extern Ctlr mach32;
|
||||
|
|
Loading…
Reference in a new issue