audioac97: support for ICH4-ICH7 based cards with memory mapped registers (thanks echoline)
This commit is contained in:
parent
978628d679
commit
7a145e89b3
1 changed files with 93 additions and 34 deletions
|
@ -50,6 +50,9 @@ struct Ctlr {
|
||||||
|
|
||||||
ulong port;
|
ulong port;
|
||||||
ulong mixport;
|
ulong mixport;
|
||||||
|
uchar *mmreg;
|
||||||
|
uchar *mmmix;
|
||||||
|
int ismmio;
|
||||||
|
|
||||||
Ring inring, micring, outring;
|
Ring inring, micring, outring;
|
||||||
|
|
||||||
|
@ -61,9 +64,6 @@ struct Ctlr {
|
||||||
Ctlr *next;
|
Ctlr *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define iorl(c, r) (inl((c)->port+(r)))
|
|
||||||
#define iowl(c, r, l) (outl((c)->port+(r), (ulong)(l)))
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
In = 0x00,
|
In = 0x00,
|
||||||
Out = 0x10,
|
Out = 0x10,
|
||||||
|
@ -192,12 +192,50 @@ writering(Ring *r, uchar *p, long n)
|
||||||
return n0 - n;
|
return n0 - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define csr8r(c, r) (inb((c)->port+(r)))
|
static uchar
|
||||||
#define csr16r(c, r) (ins((c)->port+(r)))
|
csr8r(Ctlr *c, int r){
|
||||||
#define csr32r(c, r) (inl((c)->port+(r)))
|
if(c->ismmio)
|
||||||
#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
|
return *(uchar*)(c->mmreg+r);
|
||||||
#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
|
return inb(c->port+r);
|
||||||
#define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w)))
|
}
|
||||||
|
|
||||||
|
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 */
|
/* audioac97mix */
|
||||||
extern void ac97mixreset(Audio *,
|
extern void ac97mixreset(Audio *,
|
||||||
|
@ -210,13 +248,12 @@ ac97waitcodec(Audio *adev)
|
||||||
Ctlr *ctlr;
|
Ctlr *ctlr;
|
||||||
int i;
|
int i;
|
||||||
ctlr = adev->ctlr;
|
ctlr = adev->ctlr;
|
||||||
for(i = 0; i < Maxbusywait/10; i++){
|
for(i = 0; i <= Maxbusywait/10; i++){
|
||||||
if((csr8r(ctlr, Cas) & Casp) == 0)
|
if((csr8r(ctlr, Cas) & Casp) == 0)
|
||||||
break;
|
return;
|
||||||
microdelay(10);
|
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
|
static void
|
||||||
|
@ -225,7 +262,10 @@ ac97mixw(Audio *adev, int port, ushort val)
|
||||||
Ctlr *ctlr;
|
Ctlr *ctlr;
|
||||||
ac97waitcodec(adev);
|
ac97waitcodec(adev);
|
||||||
ctlr = adev->ctlr;
|
ctlr = adev->ctlr;
|
||||||
outs(ctlr->mixport+port, val);
|
if(ctlr->ismmio)
|
||||||
|
*(ushort*)(ctlr->mmmix+port) = val;
|
||||||
|
else
|
||||||
|
outs(ctlr->mixport+port, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ushort
|
static ushort
|
||||||
|
@ -234,6 +274,8 @@ ac97mixr(Audio *adev, int port)
|
||||||
Ctlr *ctlr;
|
Ctlr *ctlr;
|
||||||
ac97waitcodec(adev);
|
ac97waitcodec(adev);
|
||||||
ctlr = adev->ctlr;
|
ctlr = adev->ctlr;
|
||||||
|
if(ctlr->ismmio)
|
||||||
|
return *(ushort*)(ctlr->mmmix+port);
|
||||||
return ins(ctlr->mixport+port);
|
return ins(ctlr->mixport+port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,27 +513,44 @@ Found:
|
||||||
adev->ctlr = ctlr;
|
adev->ctlr = ctlr;
|
||||||
ctlr->adev = adev;
|
ctlr->adev = adev;
|
||||||
|
|
||||||
if((p->mem[0].bar & 1) == 0 || (p->mem[1].bar & 1) == 0){
|
/* ICH4 through ICH7 may use memory-type base address registers */
|
||||||
print("ac97: not i/o regions 0x%04lux 0x%04lux\n", p->mem[0].bar, p->mem[1].bar);
|
if(p->vid == 0x8086 &&
|
||||||
return -1;
|
(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){
|
||||||
if(p->vid == 0x1039 && p->did == 0x7012){
|
ctlr->sis7012 = 1; /* i/o bars swapped? */
|
||||||
ctlr->sis7012 = 1;
|
}
|
||||||
//i = 0; i/o bars swaped?
|
|
||||||
}
|
ctlr->port = p->mem[1].bar & ~3;
|
||||||
ctlr->port = p->mem[i].bar & ~3;
|
if(ioalloc(ctlr->port, p->mem[1].size, 0, "ac97") < 0){
|
||||||
if(ioalloc(ctlr->port, p->mem[i].size, 0, "ac97") < 0){
|
print("ac97: ioalloc failed for port 0x%04lux\n", ctlr->port);
|
||||||
print("ac97: ioalloc failed for port 0x%04lux\n", ctlr->port);
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
ctlr->mixport = p->mem[0].bar & ~3;
|
||||||
i = (i+1) & 1;
|
if(ioalloc(ctlr->mixport, p->mem[0].size, 0, "ac97mix") < 0){
|
||||||
ctlr->mixport = p->mem[i].bar & ~3;
|
print("ac97: ioalloc failed for mixport 0x%04lux\n", ctlr->mixport);
|
||||||
if(ioalloc(ctlr->mixport, p->mem[i].size, 0, "ac97mix") < 0){
|
iofree(ctlr->port);
|
||||||
print("ac97: ioalloc failed for mixport 0x%04lux\n", ctlr->mixport);
|
return -1;
|
||||||
iofree(ctlr->port);
|
}
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
irq = p->intl;
|
irq = p->intl;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue