diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-12-05 18:32:58 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-12-05 18:32:58 +0100 |
commit | 7a145e89b301a1865661f7a6e60a21731f12824f (patch) | |
tree | 913c68ac130bdf0ea49478505ee13788ecab5f88 /sys/src | |
parent | 978628d67994819f0b3b9e2a0834d8941a21f6b5 (diff) |
audioac97: support for ICH4-ICH7 based cards with memory mapped registers (thanks echoline)
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/9/pc/audioac97.c | 127 |
1 files changed, 93 insertions, 34 deletions
diff --git a/sys/src/9/pc/audioac97.c b/sys/src/9/pc/audioac97.c index a9a1e7db1..6d11f6279 100644 --- a/sys/src/9/pc/audioac97.c +++ b/sys/src/9/pc/audioac97.c @@ -50,6 +50,9 @@ struct Ctlr { ulong port; ulong mixport; + uchar *mmreg; + uchar *mmmix; + int ismmio; Ring inring, micring, outring; @@ -61,9 +64,6 @@ struct Ctlr { Ctlr *next; }; -#define iorl(c, r) (inl((c)->port+(r))) -#define iowl(c, r, l) (outl((c)->port+(r), (ulong)(l))) - enum { In = 0x00, Out = 0x10, @@ -192,12 +192,50 @@ writering(Ring *r, uchar *p, long n) return n0 - n; } -#define csr8r(c, r) (inb((c)->port+(r))) -#define csr16r(c, r) (ins((c)->port+(r))) -#define csr32r(c, r) (inl((c)->port+(r))) -#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b))) -#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w))) -#define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w))) +static uchar +csr8r(Ctlr *c, int r){ + if(c->ismmio) + return *(uchar*)(c->mmreg+r); + return inb(c->port+r); +} + +static ushort +csr16r(Ctlr *c, int r){ + if(c->ismmio) + return *(ushort*)(c->mmreg+r); + return ins(c->port+r); +} + +static ulong +csr32r(Ctlr *c, int r){ + if(c->ismmio) + return *(ulong*)(c->mmreg+r); + return inl(c->port+r); +} + +static void +csr8w(Ctlr *c, int r, uchar v){ + if(c->ismmio) + *(uchar*)(c->mmreg+r) = v; + else + outb(c->port+r, (int)v); +} + +static void +csr16w(Ctlr *c, int r, ushort v){ + if(c->ismmio) + *(ushort*)(c->mmreg+r) = v; + else + outs(c->port+r, v); +} + +static void +csr32w(Ctlr *c, int r, ulong v){ + if(c->ismmio) + *(ulong*)(c->mmreg+r) = v; + else + outl(c->port+r, v); +} /* audioac97mix */ extern void ac97mixreset(Audio *, @@ -210,13 +248,12 @@ ac97waitcodec(Audio *adev) Ctlr *ctlr; int i; ctlr = adev->ctlr; - for(i = 0; i < Maxbusywait/10; i++){ + for(i = 0; i <= Maxbusywait/10; i++){ if((csr8r(ctlr, Cas) & Casp) == 0) - break; + return; microdelay(10); } - if(i == Maxbusywait) - print("#A%d: ac97 exhausted waiting codec access\n", adev->ctlrno); + print("#A%d: ac97 exhausted waiting codec access\n", adev->ctlrno); } static void @@ -225,7 +262,10 @@ ac97mixw(Audio *adev, int port, ushort val) Ctlr *ctlr; ac97waitcodec(adev); ctlr = adev->ctlr; - outs(ctlr->mixport+port, val); + if(ctlr->ismmio) + *(ushort*)(ctlr->mmmix+port) = val; + else + outs(ctlr->mixport+port, val); } static ushort @@ -234,6 +274,8 @@ ac97mixr(Audio *adev, int port) Ctlr *ctlr; ac97waitcodec(adev); ctlr = adev->ctlr; + if(ctlr->ismmio) + return *(ushort*)(ctlr->mmmix+port); return ins(ctlr->mixport+port); } @@ -471,27 +513,44 @@ Found: adev->ctlr = ctlr; ctlr->adev = adev; - if((p->mem[0].bar & 1) == 0 || (p->mem[1].bar & 1) == 0){ - print("ac97: not i/o regions 0x%04lux 0x%04lux\n", p->mem[0].bar, p->mem[1].bar); - return -1; - } + /* ICH4 through ICH7 may use memory-type base address registers */ + if(p->vid == 0x8086 && + (p->did == 0x24c5 || p->did == 0x24d5 || p->did == 0x266e || p->did == 0x27de) && + (p->mem[2].bar != 0 && p->mem[3].bar != 0) && + ((p->mem[2].bar & 1) == 0 && (p->mem[3].bar & 1) == 0)){ + ctlr->mmmix = vmap(p->mem[2].bar & ~0xf, p->mem[2].size); + if(ctlr->mmmix == nil){ + print("ac97: vmap failed for mmmix 0x%08lux\n", p->mem[2].bar); + return -1; + } + ctlr->mmreg = vmap(p->mem[3].bar & ~0xf, p->mem[3].size); + if(ctlr->mmreg == nil){ + print("ac97: vmap failed for mmreg 0x%08lux\n", p->mem[3].bar); + vunmap(ctlr->mmmix, p->mem[2].size); + return -1; + } + ctlr->ismmio = 1; + }else{ + if((p->mem[0].bar & 1) == 0 || (p->mem[1].bar & 1) == 0){ + print("ac97: not i/o regions 0x%04lux 0x%04lux\n", p->mem[0].bar, p->mem[1].bar); + return -1; + } - i = 1; - if(p->vid == 0x1039 && p->did == 0x7012){ - ctlr->sis7012 = 1; - //i = 0; i/o bars swaped? - } - ctlr->port = p->mem[i].bar & ~3; - if(ioalloc(ctlr->port, p->mem[i].size, 0, "ac97") < 0){ - print("ac97: ioalloc failed for port 0x%04lux\n", ctlr->port); - return -1; - } - i = (i+1) & 1; - ctlr->mixport = p->mem[i].bar & ~3; - if(ioalloc(ctlr->mixport, p->mem[i].size, 0, "ac97mix") < 0){ - print("ac97: ioalloc failed for mixport 0x%04lux\n", ctlr->mixport); - iofree(ctlr->port); - return -1; + if(p->vid == 0x1039 && p->did == 0x7012){ + ctlr->sis7012 = 1; /* i/o bars swapped? */ + } + + ctlr->port = p->mem[1].bar & ~3; + if(ioalloc(ctlr->port, p->mem[1].size, 0, "ac97") < 0){ + print("ac97: ioalloc failed for port 0x%04lux\n", ctlr->port); + return -1; + } + ctlr->mixport = p->mem[0].bar & ~3; + if(ioalloc(ctlr->mixport, p->mem[0].size, 0, "ac97mix") < 0){ + print("ac97: ioalloc failed for mixport 0x%04lux\n", ctlr->mixport); + iofree(ctlr->port); + return -1; + } } irq = p->intl; |