audiohda: make it work with qemu (thanks mischief)
the driver was not using irb interrupts and was just polling the irb write pointer to wait for command completion. this is not supported by qemu. qemu requires the use of irb interrupt handshake and it refuses to accept the next command until we acknowledge the irb interrupt.
This commit is contained in:
parent
950d970671
commit
0205392410
1 changed files with 21 additions and 7 deletions
|
@ -462,9 +462,8 @@ waitup32(Ctlr *ctlr, int reg, uint mask, uint set)
|
|||
static int
|
||||
hdacmd(Ctlr *ctlr, uint request, uint reply[2])
|
||||
{
|
||||
uint rp, wp;
|
||||
uint re;
|
||||
int wait;
|
||||
uint rp, wp, re;
|
||||
int wait, ret;
|
||||
|
||||
re = csr16(ctlr, Rirbwp);
|
||||
rp = csr16(ctlr, Corbrp);
|
||||
|
@ -476,15 +475,22 @@ hdacmd(Ctlr *ctlr, uint request, uint reply[2])
|
|||
ctlr->corb[wp] = request;
|
||||
coherence();
|
||||
csr16(ctlr, Corbwp) = wp;
|
||||
|
||||
ret = 0;
|
||||
for(wait=0; wait < Maxrirbwait; wait++){
|
||||
if(csr16(ctlr, Rirbwp) != re){
|
||||
re = (re + 1) % ctlr->rirbsize;
|
||||
memmove(reply, &ctlr->rirb[re*2], 8);
|
||||
return 1;
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
microdelay(1);
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* reset intcnt for qemu */
|
||||
csr8(ctlr, Rirbsts) = Rirbrover|Rirbrint;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1732,7 +1738,15 @@ hdastart(Ctlr *ctlr)
|
|||
csr32(ctlr, Rirblbase) = pa;
|
||||
csr32(ctlr, Rirbubase) = pa >> 32;
|
||||
csr16(ctlr, Rirbwp) = Rirbptrrst;
|
||||
csr8(ctlr, Rirbctl) = Rirbdma;
|
||||
|
||||
/*
|
||||
* qemu requires interrupt handshake,
|
||||
* even tho we just poll the irb write
|
||||
* pointer for command completion.
|
||||
*/
|
||||
csr16(ctlr, Rintcnt) = 1;
|
||||
csr8(ctlr, Rirbctl) = Rirbdma|Rirbint;
|
||||
|
||||
waitup8(ctlr, Rirbctl, Rirbdma, Rirbdma);
|
||||
|
||||
/* enable interrupts */
|
||||
|
|
Loading…
Reference in a new issue