From 0918ce10dc7b3e39506b8c4177e68a7b3233f5a9 Mon Sep 17 00:00:00 2001 From: ment Date: Mon, 27 Jun 2011 22:15:50 +0200 Subject: [PATCH 1/3] usb/kb: reset led state on boot --- sys/src/cmd/usb/kb/hid.h | 5 +++++ sys/src/cmd/usb/kb/kb.c | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/usb/kb/hid.h b/sys/src/cmd/usb/kb/hid.h index e89c88d0c..dba2b027d 100644 --- a/sys/src/cmd/usb/kb/hid.h +++ b/sys/src/cmd/usb/kb/hid.h @@ -10,12 +10,17 @@ enum { KbdCSP = 0x010103, /* keyboard.boot.hid */ /* Requests */ + Getreport = 0x01, + Setreport = 0x09, Getproto = 0x03, Setproto = 0x0b, /* protocols for SET_PROTO request */ Bootproto = 0, Reportproto = 1, + + /* protocols for SET_REPORT request */ + Reportout = 0x0200, }; enum { diff --git a/sys/src/cmd/usb/kb/kb.c b/sys/src/cmd/usb/kb/kb.c index bf4918cc4..0880f5b51 100644 --- a/sys/src/cmd/usb/kb/kb.c +++ b/sys/src/cmd/usb/kb/kb.c @@ -124,6 +124,12 @@ setbootproto(KDev* f, int eid) return usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0); } +static int +setleds(KDev* f, int eid, uchar leds) +{ + return usbcmd(f->dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, &leds, 1); +} + /* * Try to recover from a babble error. A port reset is the only way out. * BUG: we should be careful not to reset a bundle with several devices. @@ -537,7 +543,10 @@ kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), int accel) kd->ep = nil; return; } - + if(setleds(kd, ep->id, 0) < 0){ + fprint(2, "kb: %s: setleds: %r\n", d->dir); + return; + } incref(d); proccreate(f, kd, Stack); } From 7b6675ff1a1da63c2f738b50d3ee2eb062c3ab63 Mon Sep 17 00:00:00 2001 From: ment Date: Mon, 27 Jun 2011 23:01:58 +0200 Subject: [PATCH 2/3] audio/hda: added archfile command interface --- sys/src/9/pc/audiohda.c | 47 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/sys/src/9/pc/audiohda.c b/sys/src/9/pc/audiohda.c index 7b978f117..a58cdcd45 100644 --- a/sys/src/9/pc/audiohda.c +++ b/sys/src/9/pc/audiohda.c @@ -277,9 +277,9 @@ struct Ctlr { uchar *mem; ulong size; + Queue *q; ulong *corb; ulong corbsize; - ulong *rirb; ulong rirbsize; @@ -370,6 +370,8 @@ static char *pinloc2[] = { "other", }; +Ctlr *lastcard; + static int waitup8(Ctlr *ctlr, int reg, uchar mask, uchar set) { @@ -1264,6 +1266,45 @@ hdamatch(Pcidev *p) return nil; } +static long +hdacmdread(Chan *, void *a, long n, vlong) +{ + Ctlr *ctlr; + + ctlr = lastcard; + if(ctlr == nil) + error(Enodev); + if(n & 7) + error(Ebadarg); + return qread(ctlr->q, a, n); +} + +static long +hdacmdwrite(Chan *, void *a, long n, vlong) +{ + Ctlr *ctlr; + ulong *lp; + int i; + uint w[2]; + + ctlr = lastcard; + if(ctlr == nil) + error(Enodev); + if(n & 3) + error(Ebadarg); + lp = a; + qlock(ctlr); + for(i=0; iq, w, sizeof(w)); + } + qunlock(ctlr); + return n; +} + static int hdareset(Audio *adev) { @@ -1304,6 +1345,7 @@ Found: ctlr->no = adev->ctlrno; ctlr->size = p->mem[0].size; + ctlr->q = qopen(256, 0, 0, 0); ctlr->mem = vmap(p->mem[0].bar & ~0x0F, ctlr->size); if(ctlr->mem == nil){ print("#A%d: can't map %.8lux\n", ctlr->no, p->mem[0].bar); @@ -1345,6 +1387,8 @@ Found: adev->ctl = hdactl; intrenable(irq, hdainterrupt, adev, tbdf, "hda"); + lastcard = ctlr; + addarchfile("hdacmd", 0664, hdacmdread, hdacmdwrite); return 0; } @@ -1354,3 +1398,4 @@ audiohdalink(void) { addaudiocard("hda", hdareset); } + From 59f388e947b7f18165c1b3054df41bf540caa129 Mon Sep 17 00:00:00 2001 From: ment Date: Tue, 28 Jun 2011 01:22:34 +0200 Subject: [PATCH 3/3] audio/hda: stereo mixing --- sys/src/9/pc/audiohda.c | 154 +++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 75 deletions(-) diff --git a/sys/src/9/pc/audiohda.c b/sys/src/9/pc/audiohda.c index a58cdcd45..88d8fa3c6 100644 --- a/sys/src/9/pc/audiohda.c +++ b/sys/src/9/pc/audiohda.c @@ -202,8 +202,14 @@ enum { Asetleft = 1<<13, Asetright = 1<<12, Asetmute = 1<<7, - Aidx = 8, + Asetidx = 8, + Agetin = 0<<15, + Agetout = 1<<15, + Agetleft = 1<<13, + Agetright = 1<<15, + Agetidx = 0, Again = 0, + Againmask = 0x7f, Getconvfmt = 0xa, Setconvfmt = 0x2, }; @@ -473,78 +479,74 @@ newnid(Id id, uint nid) return id; } -/* vol is 0...127 or ~0 for 0dB; mute is 0/1 */ -static void -setoutamp(Widget *w, int mute, uint vol) +static uint +getoutamprange(Widget *w) { - uint q, r; - uint zerodb, range; - - if((w->cap & Woutampcap) == 0) - return; - + uint r; r = cmd(w->id, Getparm, Outampcap); - range = (r >> 8) & 0x7f; - zerodb = r & 127; - - q = Asetout | Asetleft | Asetright; - if(mute) - q |= Asetmute; - else if(vol == ~0) - q |= zerodb << Again; - else if(range > 0) - q |= (range * vol / 128) << Again; - - cmd(w->id, Setamp, q); + return (r >> 8) & 0x7f; } static void -getoutamp(Widget *w, int v[2]) +getoutamp(Widget *w, int vol[2]) { - uint q, r, range; - - v[0] = 0; - v[1] = 0; - + vol[0] = vol[1] = 0; if((w->cap & Woutampcap) == 0) return; - - r = cmd(w->id, Getparm, Outampcap); - range = (r >> 8) & 0x7f; - - q = (1 << 15) | (1 << 13); - r = cmd(w->id, Getamp, q); - v[0] = (r & 0x7f) * 128 / range; - - q = (1 << 15) | (0 << 13); - r = cmd(w->id, Getamp, q); - v[1] = (r & 0x7f) * 128 / range; + vol[0] = cmd(w->id, Getamp, Agetout | Agetleft) & Againmask; + vol[1] = cmd(w->id, Getamp, Agetout | Agetright) & Againmask; } - -/* vol is 0...127 or ~0 for 0dB; mute is 0/1; in is widget or nil for all */ + +/* vol is 0...range or nil for 0dB; mute is 0/1 */ static void -setinamp(Widget *w, Widget *in, int mute, uint vol) +setoutamp(Widget *w, int mute, int *vol) { uint q, r, i; - uint zerodb, range; + uint zerodb; + + if((w->cap & Woutampcap) == 0) + return; + + r = cmd(w->id, Getparm, Outampcap); + zerodb = r & 0x7f; + + for(i=0; i<2; i++){ + q = Asetout | (i == 0 ? Asetleft : Asetright); + if(mute) + q |= Asetmute; + else if(vol == nil) + q |= zerodb << Again; + else + q |= vol[i] << Again; + cmd(w->id, Setamp, q); + } +} + +/* vol is 0...range or nil for 0dB; mute is 0/1; in is widget or nil for all */ +static void +setinamp(Widget *w, Widget *in, int mute, int *vol) +{ + uint q, r, i, j; + uint zerodb; if((w->cap & Winampcap) == 0) return; r = cmd(w->id, Getparm, Inampcap); - range = (r >> 8) & 0x7f; - zerodb = r & 127; - - q = Asetin | Asetleft | Asetright; - if(mute) - q |= Asetmute; - else if(vol == ~0) - q |= zerodb << Again; - else if(range > 0) - q |= (range * vol / 128) << Again; - for(i=0; inlist; i++){ - if(in == nil || w->list[i] == in) - cmd(w->id, Setamp, q | (i << Aidx)); + zerodb = r & 0x7f; + + for(i=0; i<2; i++){ + q = Asetin | (i == 0 ? Asetleft : Asetright); + if(mute) + q |= Asetmute; + else if(vol == nil) + q |= zerodb << Again; + else + q |= vol[i] << Again; + for(j=0; jnlist; j++){ + if(in == nil || w->list[j] == in) + cmd(w->id, Setamp, q | (j << Asetidx)); + } } } @@ -585,14 +587,14 @@ connectpath(Widget *src, Widget *dst, uint stream) uint i; for(w=src->fg->first; w != nil; w=w->next){ - setoutamp(w, 1, 0); - setinamp(w, nil, 1, 0); + setoutamp(w, 1, nil); + setinamp(w, nil, 1, nil); cmd(w->id, Setstream, 0); } for(w=dst; w != src; w=v){ v = w->from; - setoutamp(w, 0, ~0); - setinamp(v, w, 0, ~0); + setoutamp(w, 0, nil); + setinamp(v, w, 0, nil); if(v->type == Waout || v->type == Wamix) continue; if(v->nlist == 1) @@ -601,7 +603,7 @@ connectpath(Widget *src, Widget *dst, uint stream) ; cmd(v->id, Setconn, i); } - setoutamp(src, 0, ~0); + setoutamp(src, 0, nil); cmd(src->id, Setpinctl, Pinctlout); cmd(dst->id, Setstream, (stream << 4) | 0); cmd(dst->id, Setconvfmt, (1 << 14) | (1 << 4) | 1); @@ -1044,9 +1046,7 @@ hdactl(Audio *adev, void *va, long n, vlong) if(ntok <= 0) continue; if(cistrcmp(tok[0], "pin") == 0 && ntok == 2){ - qlock(ctlr); connectpin(ctlr, strtoul(tok[1], 0, 0)); - qunlock(ctlr); }else error(Ebadctl); } @@ -1101,12 +1101,8 @@ static int hdagetvol(Audio *adev, int, int a[2]) { Ctlr *ctlr = adev->ctlr; - - if(ctlr->amp == nil) - return -1; - qlock(ctlr); - getoutamp(ctlr->amp, a); - qunlock(ctlr); + if(ctlr->amp != nil) + getoutamp(ctlr->amp, a); return 0; } @@ -1114,24 +1110,32 @@ static int hdasetvol(Audio *adev, int, int a[2]) { Ctlr *ctlr = adev->ctlr; - - if(ctlr->amp == nil) - return -1; - qlock(ctlr); - setoutamp(ctlr->amp, 0, a[0]); - qunlock(ctlr); + if(ctlr->amp != nil) + setoutamp(ctlr->amp, 0, a); return 0; } +static void +fillvoltab(Ctlr *ctlr, Volume *vt) +{ + memmove(vt, voltab, sizeof(voltab)); + if(ctlr->amp != nil) + vt[0].range = getoutamprange(ctlr->amp); +} + static long hdavolread(Audio *adev, void *a, long n, vlong) { + Volume voltab[2]; + fillvoltab(adev->ctlr, voltab); return genaudiovolread(adev, a, n, 0, voltab, hdagetvol, 0); } static long hdavolwrite(Audio *adev, void *a, long n, vlong) { + Volume voltab[2]; + fillvoltab(adev->ctlr, voltab); return genaudiovolwrite(adev, a, n, 0, voltab, hdasetvol, 0); }