From e4875c1ae7fd5dd0439f77119548349f4bfd981c Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 19 Jan 2013 01:12:39 +0100 Subject: [PATCH] audiohda: first attempt on audio recording support for intel hda audio, distinguish mode in audio code --- sys/src/9/pc/audioac97.c | 9 +- sys/src/9/pc/audiohda.c | 457 +++++++++++++++++++++++++------------- sys/src/9/pc/audiosb16.c | 4 +- sys/src/9/port/audioif.h | 2 +- sys/src/9/port/devaudio.c | 2 +- 5 files changed, 309 insertions(+), 165 deletions(-) diff --git a/sys/src/9/pc/audioac97.c b/sys/src/9/pc/audioac97.c index 5bb5b0cf9..3149458ad 100644 --- a/sys/src/9/pc/audioac97.c +++ b/sys/src/9/pc/audioac97.c @@ -306,14 +306,14 @@ static int inavail(void *arg) { Ring *r = arg; - return buffered(r); + return buffered(r) > 0; } static int outavail(void *arg) { Ring *r = arg; - return available(r); + return available(r) > 0; } static int @@ -386,12 +386,15 @@ ac97write(Audio *adev, void *vp, long n, vlong) } static void -ac97close(Audio *adev) +ac97close(Audio *adev, int mode) { Ctlr *ctlr; Ring *ring; uchar z[1]; + if(mode == OREAD) + return; + z[0] = 0; ctlr = adev->ctlr; ring = &ctlr->outring; diff --git a/sys/src/9/pc/audiohda.c b/sys/src/9/pc/audiohda.c index e0f88b323..b0b241a95 100644 --- a/sys/src/9/pc/audiohda.c +++ b/sys/src/9/pc/audiohda.c @@ -11,6 +11,8 @@ typedef struct Codec Codec; typedef struct Ctlr Ctlr; typedef struct Bld Bld; typedef struct Ring Ring; +typedef struct Stream Stream; + typedef struct Id Id; typedef struct Widget Widget; typedef struct Codec Codec; @@ -226,6 +228,26 @@ struct Ring { ulong wi; }; +struct Stream { + Ring ring; + + Bld *blds; + + uint sdctl; + uint sdintr; + uint sdnum; + + uint afmt; + uint atag; + int active; + + uint pin; + uint cad; + + Widget *conv; /* DAC or ADC */ + Widget *jack; /* the pin jack */ +}; + struct Id { Ctlr *ctlr; uint codec, nid; @@ -245,8 +267,10 @@ struct Widget { uint convrate, convfmt; }; }; - Widget *next; - Widget *from; + Widget *next; /* next in function group */ + Widget *path; /* next in audio path */ + + Widget *link; /* temporary for findpath */ }; struct Fungroup { @@ -254,8 +278,6 @@ struct Fungroup { Codec *codec; uint type; Widget *first; - Widget *mixer; - Widget *src, *dst; Fungroup *next; }; @@ -294,25 +316,13 @@ struct Ctlr { ulong *rirb; ulong rirbsize; - uint sdctl; - uint sdintr; - uint sdnum; - - Bld *blds; - - Ring ring; + Stream sout; + Stream sin; uint iss, oss, bss; uint codecmask; Codec *codec[Maxcodecs]; - - Widget *amp, *src; - uint pin; - uint cad; - - int active; - uint afmt, atag; }; #define csr32(c, r) (*(ulong *)&(c)->mem[r]) @@ -589,55 +599,84 @@ setinamp(Widget *w, Widget *in, int mute, int *vol) } static Widget * -findpath(Widget *src) +findpath(Widget *jack, int type) { Widget *q[Maxwidgets]; uint l, r, i; - Widget *w, *v; - + Widget *w, *to; + l = r = 0; - q[r++] = src; - for(w=src->fg->first; w; w=w->next) - w->from = nil; - src->from = src; + for(w=jack->fg->first; w != nil; w = w->next) + w->link = nil; + + if(type == Waout){ + q[r++] = jack; + jack->link = jack; + } else { + for(w=jack->fg->first; w != nil; w = w->next) + if(w->type == type){ + q[r++] = w; + w->link = w; + } + } while(l < r){ w = q[l++]; - if(w->type == Waout) + if(type == Waout){ + if(w->type == type) + return w; + } else if(w == jack){ + for(w = jack->link; w != nil; w = w->link) + if(w->type == type) + return w; break; + } for(i=0; inlist; i++){ - v = w->list[i]; - if(v == nil || v->from) + to = w->list[i]; + if(to == nil || to->link) continue; - v->from = w; - q[r++] = v; + to->link = w; + q[r++] = to; } } - if(w->type != Waout) - return nil; - return w; + + return nil; } static void -connectpath(Widget *src, Widget *dst) +disconnectpath(Widget *from, Widget *to) { - Widget *w, *v; + Widget *next; + + for(; from != nil && from != to; from = next){ + next = from->path; + from->path = nil; + setoutamp(from, 1, nil); + setinamp(next, from, 1, nil); + } + setoutamp(to, 1, nil); +} + +static void +connectpath(Widget *from, Widget *to) +{ + Widget *next; uint i; - for(w=dst; w != src; w=v){ - v = w->from; - setoutamp(w, 0, nil); - setinamp(v, w, 0, nil); - if(v->nlist == 1) + for(; from != nil && from != to; from = next){ + next = from->link; + from->path = next; + setoutamp(from, 0, nil); + setinamp(next, from, 0, nil); + if(next->nlist == 1) continue; - for(i=0; i < v->nlist; i++) - if(v->list[i] == w){ - cmd(v->id, Setconn, i); + for(i=0; i < next->nlist; i++) + if(next->list[i] == from){ + cmd(next->id, Setconn, i); break; } } - setoutamp(src, 0, nil); - cmd(src->id, Setpinctl, Pinctlout); + setoutamp(to, 0, nil); } static void @@ -844,41 +883,48 @@ enumdev(Ctlr *ctlr) } static int -connectpin(Ctlr *ctlr, uint pin, uint cad) +connectpin(Ctlr *ctlr, Stream *s, int type, uint pin, uint cad) { - Widget *w, *src, *dst; + Widget *jack, *conv; if(cad >= Maxcodecs || pin >= Maxwidgets || ctlr->codec[cad] == nil) return -1; - src = ctlr->codec[cad]->widgets[pin]; - if(src == nil) + jack = ctlr->codec[cad]->widgets[pin]; + if(jack == nil) return -1; - if(src->type != Wpin) - return -1; - if((src->pincap & Pout) == 0) + if(jack->type != Wpin) return -1; - dst = findpath(src); - if(dst == nil) + conv = findpath(jack, type); + if(conv == nil) return -1; - /* mute all widgets, clear stream */ - for(w=src->fg->first; w != nil; w=w->next){ - setoutamp(w, 1, nil); - setinamp(w, nil, 1, nil); - cmd(w->id, Setstream, 0); + if(s->conv != nil && s->jack != nil){ + if(s->conv->type == Waout) + disconnectpath(s->conv, s->jack); + else + disconnectpath(s->jack, s->conv); + cmd(s->conv->id, Setstream, 0); + cmd(s->jack->id, Setpinctl, 0); } - connectpath(src, dst); + if(type == Waout){ + connectpath(conv, jack); + cmd(jack->id, Setpinctl, Pinctlout); + } else { + connectpath(jack, conv); + cmd(jack->id, Setpinctl, Pinctlin); + } - cmd(dst->id, Setconvfmt, ctlr->afmt); - cmd(dst->id, Setstream, (ctlr->atag << 4) | 0); - cmd(dst->id, Setchancnt, 1); + cmd(conv->id, Setconvfmt, s->afmt); + cmd(conv->id, Setstream, (s->atag << 4) | 0); + cmd(conv->id, Setchancnt, 1); + + s->conv = conv; + s->jack = jack; + s->pin = pin; + s->cad = cad; - ctlr->amp = dst; - ctlr->src = src; - ctlr->pin = pin; - ctlr->cad = cad; return 0; } @@ -949,6 +995,29 @@ available(Ring *r) return m; } +static long +readring(Ring *r, uchar *p, long n) +{ + long n0, m; + + n0 = n; + while(n > 0){ + if((m = buffered(r)) <= 0) + break; + if(m > n) + m = n; + if(p){ + if(r->ri + m > r->nbuf) + m = r->nbuf - r->ri; + memmove(p, r->buf + r->ri, m); + p += m; + } + r->ri = (r->ri + m) % r->nbuf; + n -= m; + } + return n0 - n; +} + static long writering(Ring *r, uchar *p, long n) { @@ -973,93 +1042,87 @@ writering(Ring *r, uchar *p, long n) } static int -streamalloc(Ctlr *ctlr) +streamalloc(Ctlr *ctlr, Stream *s, int num) { Ring *r; int i; - r = &ctlr->ring; - memset(r, 0, sizeof(*r)); + r = &s->ring; r->buf = xspanalloc(r->nbuf = Bufsize, 128, 0); - ctlr->blds = xspanalloc(Nblocks * sizeof(Bld), 128, 0); - if(r->buf == nil || ctlr->blds == nil){ + s->blds = xspanalloc(Nblocks * sizeof(Bld), 128, 0); + if(r->buf == nil || s->blds == nil){ print("hda: no memory for stream\n"); return -1; } for(i=0; iblds[i].addrlo = PADDR(r->buf) + i*Blocksize; - ctlr->blds[i].addrhi = 0; - ctlr->blds[i].len = Blocksize; - ctlr->blds[i].flags = 0x01; /* interrupt on completion */ + s->blds[i].addrlo = PADDR(r->buf) + i*Blocksize; + s->blds[i].addrhi = 0; + s->blds[i].len = Blocksize; + s->blds[i].flags = 0x01; /* interrupt on completion */ } - /* output dma engine starts after inputs */ - ctlr->sdnum = ctlr->iss; - ctlr->sdctl = Sdctl0 + ctlr->sdnum*0x20; - ctlr->sdintr = 1<sdnum; - ctlr->atag = ctlr->sdnum+1; - ctlr->afmt = Fmtstereo | Fmtsampw | Fmtdiv1 | Fmtmul1 | Fmtbase441; - ctlr->active = 0; + s->sdnum = num; + s->sdctl = Sdctl0 + s->sdnum*0x20; + s->sdintr = 1<sdnum; + s->atag = s->sdnum+1; + s->afmt = Fmtstereo | Fmtsampw | Fmtdiv1 | Fmtmul1 | Fmtbase441; + s->active = 0; /* perform reset */ - csr8(ctlr, ctlr->sdctl) &= ~(Srst | Srun | Scie | Seie | Sdie); - csr8(ctlr, ctlr->sdctl) |= Srst; + csr8(ctlr, s->sdctl) &= ~(Srst | Srun | Scie | Seie | Sdie); + csr8(ctlr, s->sdctl) |= Srst; microdelay(Codecdelay); - waitup8(ctlr, ctlr->sdctl, Srst, Srst); - csr8(ctlr, ctlr->sdctl) &= ~Srst; + waitup8(ctlr, s->sdctl, Srst, Srst); + csr8(ctlr, s->sdctl) &= ~Srst; microdelay(Codecdelay); - waitup8(ctlr, ctlr->sdctl, Srst, 0); + waitup8(ctlr, s->sdctl, Srst, 0); /* set stream number */ - csr32(ctlr, ctlr->sdctl) = (ctlr->atag << Stagbit) | - (csr32(ctlr, ctlr->sdctl) & ~(0xF << Stagbit)); + csr32(ctlr, s->sdctl) = (s->atag << Stagbit) | + (csr32(ctlr, s->sdctl) & ~(0xF << Stagbit)); /* set stream format */ - csr16(ctlr, Sdfmt+ctlr->sdctl) = ctlr->afmt; + csr16(ctlr, Sdfmt+s->sdctl) = s->afmt; /* program stream DMA & parms */ - csr32(ctlr, Sdbdplo+ctlr->sdctl) = PADDR(ctlr->blds); - csr32(ctlr, Sdbdphi+ctlr->sdctl) = 0; - csr32(ctlr, Sdcbl+ctlr->sdctl) = r->nbuf; - csr16(ctlr, Sdlvi+ctlr->sdctl) = (Nblocks - 1) & 0xff; + csr32(ctlr, Sdbdplo+s->sdctl) = PADDR(s->blds); + csr32(ctlr, Sdbdphi+s->sdctl) = 0; + csr32(ctlr, Sdcbl+s->sdctl) = r->nbuf; + csr16(ctlr, Sdlvi+s->sdctl) = (Nblocks - 1) & 0xff; /* mask out ints */ - csr8(ctlr, Sdsts+ctlr->sdctl) = Scompl | Sfifoerr | Sdescerr; + csr8(ctlr, Sdsts+s->sdctl) = Scompl | Sfifoerr | Sdescerr; /* enable global intrs for this stream */ - csr32(ctlr, Intctl) |= ctlr->sdintr; - csr8(ctlr, ctlr->sdctl) |= Scie | Seie | Sdie; + csr32(ctlr, Intctl) |= s->sdintr; + csr8(ctlr, s->sdctl) |= Scie | Seie | Sdie; return 0; } static void -streamstart(Ctlr *ctlr) +streamstart(Ctlr *ctlr, Stream *s) { - ctlr->active = 1; - - csr8(ctlr, ctlr->sdctl) |= Srun; - waitup8(ctlr, ctlr->sdctl, Srun, Srun); + s->active = 1; + csr8(ctlr, s->sdctl) |= Srun; + waitup8(ctlr, s->sdctl, Srun, Srun); } static void -streamstop(Ctlr *ctlr) +streamstop(Ctlr *ctlr, Stream *s) { - csr8(ctlr, ctlr->sdctl) &= ~Srun; - waitup8(ctlr, ctlr->sdctl, Srun, 0); - - ctlr->active = 0; + csr8(ctlr, s->sdctl) &= ~Srun; + waitup8(ctlr, s->sdctl, Srun, 0); + s->active = 0; } static uint -streampos(Ctlr *ctlr) +streampos(Ctlr *ctlr, Stream *s) { - Ring *r; uint p; - r = &ctlr->ring; - p = csr32(ctlr, Sdlpib+ctlr->sdctl); - if(p >= r->nbuf) + p = csr32(ctlr, Sdlpib+s->sdctl); + if(p >= s->ring.nbuf) p = 0; return p; } @@ -1085,22 +1148,38 @@ hdactl(Audio *adev, void *va, long n, vlong) if(ntok <= 0) continue; if(cistrcmp(tok[0], "pin") == 0 && ntok >= 2){ - cad = ctlr->cad; + cad = ctlr->sout.cad; pin = strtoul(tok[1], 0, 0); if(ntok > 2) cad = strtoul(tok[2], 0, 0); - connectpin(ctlr, pin, cad); + if(connectpin(ctlr, &ctlr->sout, Waout, pin, cad) < 0) + error("connectpin failed"); + }else + if(cistrcmp(tok[0], "inpin") == 0 && ntok >= 2){ + cad = ctlr->sout.cad; + pin = strtoul(tok[1], 0, 0); + if(ntok > 2) + cad = strtoul(tok[2], 0, 0); + if(connectpin(ctlr, &ctlr->sin, Wain, pin, cad) < 0) + error("connectpin failed"); }else error(Ebadctl); } return n; } +static int +inavail(void *arg) +{ + Ring *r = arg; + return buffered(r) > 0; +} + static int outavail(void *arg) { - Ctlr *ctlr = arg; - return available(&ctlr->ring) > 0; + Ring *r = arg; + return available(r) > 0; } static int @@ -1108,7 +1187,7 @@ outrate(void *arg) { Ctlr *ctlr = arg; int delay = ctlr->adev->delay*BytesPerSample; - return (delay <= 0) || (buffered(&ctlr->ring) <= delay) || (ctlr->active == 0); + return (delay <= 0) || (buffered(&ctlr->sout.ring) <= delay) || (ctlr->sout.active == 0); } static long @@ -1116,16 +1195,41 @@ hdabuffered(Audio *adev) { Ctlr *ctlr; ctlr = adev->ctlr; - return buffered(&ctlr->ring); + return buffered(&ctlr->sout.ring); } static void hdakick(Ctlr *ctlr) { - if(ctlr->active) + if(ctlr->sout.active) return; - if(buffered(&ctlr->ring) > Blocksize) - streamstart(ctlr); + if(buffered(&ctlr->sout.ring) > Blocksize) + streamstart(ctlr, &ctlr->sout); +} + +static long +hdaread(Audio *adev, void *vp, long n, vlong) +{ + uchar *p, *e; + Ctlr *ctlr; + Ring *ring; + + p = vp; + e = p + n; + ctlr = adev->ctlr; + ring = &ctlr->sin.ring; + if(ring->buf == nil || ctlr->sin.conv == nil) + return 0; + while(p < e) { + if((n = readring(ring, p, e - p)) <= 0){ + if(!ctlr->sin.active) + streamstart(ctlr, &ctlr->sin); + sleep(&ring->r, inavail, ring); + continue; + } + p += n; + } + return p - (uchar*)vp; } static long @@ -1138,11 +1242,11 @@ hdawrite(Audio *adev, void *vp, long n, vlong) p = vp; e = p + n; ctlr = adev->ctlr; - ring = &ctlr->ring; + ring = &ctlr->sout.ring; while(p < e) { if((n = writering(ring, p, e - p)) <= 0){ hdakick(ctlr); - sleep(&ring->r, outavail, ctlr); + sleep(&ring->r, outavail, ring); continue; } p += n; @@ -1153,23 +1257,28 @@ hdawrite(Audio *adev, void *vp, long n, vlong) } static void -hdaclose(Audio *adev) +hdaclose(Audio *adev, int mode) { Ctlr *ctlr; uchar z[1]; - Ring *r; ctlr = adev->ctlr; - if(!ctlr->active) - return; - z[0] = 0; - r = &ctlr->ring; - while(r->wi % Blocksize) - hdawrite(adev, z, sizeof(z), 0); + if(mode == OREAD || mode == ORDWR){ + if(ctlr->sin.active) + streamstop(ctlr, &ctlr->sin); + } + if(mode == OWRITE || mode == ORDWR){ + if(ctlr->sout.active){ + z[0] = 0; + while(ctlr->sout.ring.wi % Blocksize) + hdawrite(adev, z, sizeof(z), 0); + } + } } enum { Vmaster, + Vrecord, Vspeed, Vdelay, Nvol, @@ -1177,6 +1286,7 @@ enum { static Volume voltab[] = { [Vmaster] "master", 0, 0x7f, Stereo, 0, + [Vrecord] "record", 0, 0x7f, Stereo, 0, [Vspeed] "speed", 0, 0, Absolute, 0, [Vdelay] "delay", 0, 0, Absolute, 0, 0 @@ -1189,8 +1299,8 @@ hdagetvol(Audio *adev, int x, int a[2]) switch(x){ case Vmaster: - if(ctlr->amp != nil) - getoutamp(ctlr->amp, a); + if(ctlr->sout.conv != nil) + getoutamp(ctlr->sout.conv, a); break; case Vspeed: a[0] = adev->speed; @@ -1209,8 +1319,12 @@ hdasetvol(Audio *adev, int x, int a[2]) switch(x){ case Vmaster: - if(ctlr->amp != nil) - setoutamp(ctlr->amp, 0, a); + if(ctlr->sout.conv != nil) + setoutamp(ctlr->sout.conv, 0, a); + break; + case Vrecord: + if(ctlr->sin.conv != nil) + setinamp(ctlr->sin.conv, nil, 0, a); break; case Vspeed: adev->speed = a[0]; @@ -1226,8 +1340,8 @@ static void fillvoltab(Ctlr *ctlr, Volume *vt) { memmove(vt, voltab, sizeof(voltab)); - if(ctlr->amp != nil) - vt[Vmaster].range = getoutamprange(ctlr->amp); + if(ctlr->sout.conv != nil) + vt[Vmaster].range = getoutamprange(ctlr->sout.conv); } static long @@ -1251,22 +1365,32 @@ hdainterrupt(Ureg *, void *arg) { Ctlr *ctlr; Audio *adev; - uint sts; Ring *r; + uint sts; adev = arg; ctlr = adev->ctlr; - ilock(ctlr); sts = csr32(ctlr, Intsts); - if(sts & ctlr->sdintr){ - /* ack interrupt */ - csr8(ctlr, Sdsts+ctlr->sdctl) |= Scompl; - r = &ctlr->ring; - r->ri = streampos(ctlr); - if(ctlr->active && buffered(r) < Blocksize){ - streamstop(ctlr); - r->ri = r->wi = streampos(ctlr); + if(sts & ctlr->sout.sdintr){ + csr8(ctlr, Sdsts+ctlr->sout.sdctl) |= Scompl; + + r = &ctlr->sout.ring; + r->ri = streampos(ctlr, &ctlr->sout); + if(ctlr->sout.active && buffered(r) < Blocksize){ + streamstop(ctlr, &ctlr->sout); + r->ri = r->wi = streampos(ctlr, &ctlr->sout); + } + wakeup(&r->r); + } + if(sts & ctlr->sin.sdintr){ + csr8(ctlr, Sdsts+ctlr->sin.sdctl) |= Scompl; + + r = &ctlr->sin.ring; + r->wi = streampos(ctlr, &ctlr->sin); + if(ctlr->sin.active && available(r) < Blocksize){ + streamstop(ctlr, &ctlr->sin); + r->ri = r->wi = streampos(ctlr, &ctlr->sin); } wakeup(&r->r); } @@ -1286,20 +1410,21 @@ hdastatus(Audio *adev, void *a, long n, vlong) s = a; e = s + n; - s = seprint(s, e, "bufsize %6d buffered %6ld\n", Blocksize, buffered(&ctlr->ring)); + s = seprint(s, e, "bufsize %6d buffered %6ld\n", Blocksize, buffered(&ctlr->sout.ring)); for(i=0; icodec[i]) == nil) continue; - s = seprint(s, e, "codec %2d pin %3d\n", - codec->id.codec, ctlr->pin); + s = seprint(s, e, "codec %2d pin %3d inpin %3d\n", + codec->id.codec, ctlr->sout.pin, ctlr->sin.pin); for(fg=codec->fgroup; fg; fg=fg->next){ for(w=fg->first; w; w=w->next){ if(w->type != Wpin) continue; r = w->pin; - s = seprint(s, e, "pin %3d %s %s %s %s %s %s%s%s\n", + s = seprint(s, e, "pin %3d %s%s %s %s %s %s %s%s%s\n", w->id.nid, - (w->pincap & Pout) != 0 ? "out" : "in", + (w->pincap & Pin) != 0 ? "in" : "", + (w->pincap & Pout) != 0 ? "out" : "", pinport[(r >> 30) & 0x3], pinloc2[(r >> 28) & 0x3], pinloc[(r >> 24) & 0xf], @@ -1312,11 +1437,21 @@ hdastatus(Audio *adev, void *a, long n, vlong) } } - s = seprint(s, e, "path "); - for(w=ctlr->amp; w != nil; w = w->from){ + s = seprint(s, e, "outpath "); + for(w=ctlr->sout.conv; w != nil; w = w->path){ s = seprint(s, e, "%s %3d %lux %lux %lux", widtype[w->type&7], w->id.nid, (ulong)w->cap, (ulong)w->pin, (ulong)w->pincap); - if(w == ctlr->src) + if(w == ctlr->sout.jack) + break; + s = seprint(s, e, " → "); + } + s = seprint(s, e, "\n"); + + s = seprint(s, e, "inpath "); + for(w=ctlr->sin.jack; w != nil; w = w->path){ + s = seprint(s, e, "%s %3d %lux %lux %lux", widtype[w->type&7], w->id.nid, + (ulong)w->cap, (ulong)w->pin, (ulong)w->pincap); + if(w == ctlr->sin.conv) break; s = seprint(s, e, " → "); } @@ -1561,10 +1696,13 @@ Found: print("#A%d: unable to start hda\n", ctlr->no); return -1; } - if(streamalloc(ctlr) < 0){ - print("#A%d: streamalloc failed\n", ctlr->no); + if(streamalloc(ctlr, &ctlr->sout, ctlr->iss) < 0){ + print("#A%d: output streamalloc failed\n", ctlr->no); return -1; } + if(ctlr->iss > 0) + if(streamalloc(ctlr, &ctlr->sin, 0) < 0) + print("#A%d: input streamalloc failed\n", ctlr->no); if(enumdev(ctlr) < 0){ print("#A%d: no audio codecs found\n", ctlr->no); return -1; @@ -1574,11 +1712,12 @@ Found: print("#A%d: no output pins found!\n", ctlr->no); return -1; } - if(connectpin(ctlr, best, cad) < 0){ + if(connectpin(ctlr, &ctlr->sout, Waout, best, cad) < 0){ print("#A%d: error connecting pin\n", ctlr->no); return -1; } + adev->read = hdaread; adev->write = hdawrite; adev->close = hdaclose; adev->buffered = hdabuffered; diff --git a/sys/src/9/pc/audiosb16.c b/sys/src/9/pc/audiosb16.c index 09cc6f8be..564a11821 100644 --- a/sys/src/9/pc/audiosb16.c +++ b/sys/src/9/pc/audiosb16.c @@ -554,10 +554,12 @@ audiowrite(Audio *adev, void *vp, long n, vlong) } static void -audioclose(Audio *adev) +audioclose(Audio *adev, int mode) { Ctlr *ctlr; + if(mode == OREAD) + return; ctlr = adev->ctlr; sleep(&ctlr->vous, inactive, ctlr); setempty(ctlr); diff --git a/sys/src/9/port/audioif.h b/sys/src/9/port/audioif.h index d82c166c2..d202fa867 100644 --- a/sys/src/9/port/audioif.h +++ b/sys/src/9/port/audioif.h @@ -13,7 +13,7 @@ struct Audio long (*read)(Audio *, void *, long, vlong); long (*write)(Audio *, void *, long, vlong); - void (*close)(Audio *); + void (*close)(Audio *, int); long (*volread)(Audio *, void *, long, vlong); long (*volwrite)(Audio *, void *, long, vlong); diff --git a/sys/src/9/port/devaudio.c b/sys/src/9/port/devaudio.c index eceed5af0..21aa6f136 100644 --- a/sys/src/9/port/devaudio.c +++ b/sys/src/9/port/devaudio.c @@ -311,7 +311,7 @@ audioclose(Chan *c) if((c->qid.path == Qaudio) && (c->flag & COPEN)){ if(adev->close){ if(!waserror()){ - adev->close(adev); + adev->close(adev, c->mode); poperror(); } }