merge
This commit is contained in:
commit
81a19e0dc5
3 changed files with 140 additions and 77 deletions
|
@ -202,8 +202,14 @@ enum {
|
||||||
Asetleft = 1<<13,
|
Asetleft = 1<<13,
|
||||||
Asetright = 1<<12,
|
Asetright = 1<<12,
|
||||||
Asetmute = 1<<7,
|
Asetmute = 1<<7,
|
||||||
Aidx = 8,
|
Asetidx = 8,
|
||||||
|
Agetin = 0<<15,
|
||||||
|
Agetout = 1<<15,
|
||||||
|
Agetleft = 1<<13,
|
||||||
|
Agetright = 1<<15,
|
||||||
|
Agetidx = 0,
|
||||||
Again = 0,
|
Again = 0,
|
||||||
|
Againmask = 0x7f,
|
||||||
Getconvfmt = 0xa,
|
Getconvfmt = 0xa,
|
||||||
Setconvfmt = 0x2,
|
Setconvfmt = 0x2,
|
||||||
};
|
};
|
||||||
|
@ -277,9 +283,9 @@ struct Ctlr {
|
||||||
uchar *mem;
|
uchar *mem;
|
||||||
ulong size;
|
ulong size;
|
||||||
|
|
||||||
|
Queue *q;
|
||||||
ulong *corb;
|
ulong *corb;
|
||||||
ulong corbsize;
|
ulong corbsize;
|
||||||
|
|
||||||
ulong *rirb;
|
ulong *rirb;
|
||||||
ulong rirbsize;
|
ulong rirbsize;
|
||||||
|
|
||||||
|
@ -370,6 +376,8 @@ static char *pinloc2[] = {
|
||||||
"other",
|
"other",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Ctlr *lastcard;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
waitup8(Ctlr *ctlr, int reg, uchar mask, uchar set)
|
waitup8(Ctlr *ctlr, int reg, uchar mask, uchar set)
|
||||||
{
|
{
|
||||||
|
@ -471,78 +479,74 @@ newnid(Id id, uint nid)
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vol is 0...127 or ~0 for 0dB; mute is 0/1 */
|
static uint
|
||||||
static void
|
getoutamprange(Widget *w)
|
||||||
setoutamp(Widget *w, int mute, uint vol)
|
|
||||||
{
|
{
|
||||||
uint q, r;
|
uint r;
|
||||||
uint zerodb, range;
|
|
||||||
|
|
||||||
if((w->cap & Woutampcap) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
r = cmd(w->id, Getparm, Outampcap);
|
r = cmd(w->id, Getparm, Outampcap);
|
||||||
range = (r >> 8) & 0x7f;
|
return (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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
getoutamp(Widget *w, int v[2])
|
getoutamp(Widget *w, int vol[2])
|
||||||
{
|
{
|
||||||
uint q, r, range;
|
vol[0] = vol[1] = 0;
|
||||||
|
|
||||||
v[0] = 0;
|
|
||||||
v[1] = 0;
|
|
||||||
|
|
||||||
if((w->cap & Woutampcap) == 0)
|
if((w->cap & Woutampcap) == 0)
|
||||||
return;
|
return;
|
||||||
|
vol[0] = cmd(w->id, Getamp, Agetout | Agetleft) & Againmask;
|
||||||
r = cmd(w->id, Getparm, Outampcap);
|
vol[1] = cmd(w->id, Getamp, Agetout | Agetright) & Againmask;
|
||||||
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 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
|
static void
|
||||||
setinamp(Widget *w, Widget *in, int mute, uint vol)
|
setoutamp(Widget *w, int mute, int *vol)
|
||||||
{
|
{
|
||||||
uint q, r, i;
|
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)
|
if((w->cap & Winampcap) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r = cmd(w->id, Getparm, Inampcap);
|
r = cmd(w->id, Getparm, Inampcap);
|
||||||
range = (r >> 8) & 0x7f;
|
zerodb = r & 0x7f;
|
||||||
zerodb = r & 127;
|
|
||||||
|
for(i=0; i<2; i++){
|
||||||
q = Asetin | Asetleft | Asetright;
|
q = Asetin | (i == 0 ? Asetleft : Asetright);
|
||||||
if(mute)
|
if(mute)
|
||||||
q |= Asetmute;
|
q |= Asetmute;
|
||||||
else if(vol == ~0)
|
else if(vol == nil)
|
||||||
q |= zerodb << Again;
|
q |= zerodb << Again;
|
||||||
else if(range > 0)
|
else
|
||||||
q |= (range * vol / 128) << Again;
|
q |= vol[i] << Again;
|
||||||
for(i=0; i<w->nlist; i++){
|
for(j=0; j<w->nlist; j++){
|
||||||
if(in == nil || w->list[i] == in)
|
if(in == nil || w->list[j] == in)
|
||||||
cmd(w->id, Setamp, q | (i << Aidx));
|
cmd(w->id, Setamp, q | (j << Asetidx));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,14 +587,14 @@ connectpath(Widget *src, Widget *dst, uint stream)
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
for(w=src->fg->first; w != nil; w=w->next){
|
for(w=src->fg->first; w != nil; w=w->next){
|
||||||
setoutamp(w, 1, 0);
|
setoutamp(w, 1, nil);
|
||||||
setinamp(w, nil, 1, 0);
|
setinamp(w, nil, 1, nil);
|
||||||
cmd(w->id, Setstream, 0);
|
cmd(w->id, Setstream, 0);
|
||||||
}
|
}
|
||||||
for(w=dst; w != src; w=v){
|
for(w=dst; w != src; w=v){
|
||||||
v = w->from;
|
v = w->from;
|
||||||
setoutamp(w, 0, ~0);
|
setoutamp(w, 0, nil);
|
||||||
setinamp(v, w, 0, ~0);
|
setinamp(v, w, 0, nil);
|
||||||
if(v->type == Waout || v->type == Wamix)
|
if(v->type == Waout || v->type == Wamix)
|
||||||
continue;
|
continue;
|
||||||
if(v->nlist == 1)
|
if(v->nlist == 1)
|
||||||
|
@ -599,7 +603,7 @@ connectpath(Widget *src, Widget *dst, uint stream)
|
||||||
;
|
;
|
||||||
cmd(v->id, Setconn, i);
|
cmd(v->id, Setconn, i);
|
||||||
}
|
}
|
||||||
setoutamp(src, 0, ~0);
|
setoutamp(src, 0, nil);
|
||||||
cmd(src->id, Setpinctl, Pinctlout);
|
cmd(src->id, Setpinctl, Pinctlout);
|
||||||
cmd(dst->id, Setstream, (stream << 4) | 0);
|
cmd(dst->id, Setstream, (stream << 4) | 0);
|
||||||
cmd(dst->id, Setconvfmt, (1 << 14) | (1 << 4) | 1);
|
cmd(dst->id, Setconvfmt, (1 << 14) | (1 << 4) | 1);
|
||||||
|
@ -1042,9 +1046,7 @@ hdactl(Audio *adev, void *va, long n, vlong)
|
||||||
if(ntok <= 0)
|
if(ntok <= 0)
|
||||||
continue;
|
continue;
|
||||||
if(cistrcmp(tok[0], "pin") == 0 && ntok == 2){
|
if(cistrcmp(tok[0], "pin") == 0 && ntok == 2){
|
||||||
qlock(ctlr);
|
|
||||||
connectpin(ctlr, strtoul(tok[1], 0, 0));
|
connectpin(ctlr, strtoul(tok[1], 0, 0));
|
||||||
qunlock(ctlr);
|
|
||||||
}else
|
}else
|
||||||
error(Ebadctl);
|
error(Ebadctl);
|
||||||
}
|
}
|
||||||
|
@ -1099,12 +1101,8 @@ static int
|
||||||
hdagetvol(Audio *adev, int, int a[2])
|
hdagetvol(Audio *adev, int, int a[2])
|
||||||
{
|
{
|
||||||
Ctlr *ctlr = adev->ctlr;
|
Ctlr *ctlr = adev->ctlr;
|
||||||
|
if(ctlr->amp != nil)
|
||||||
if(ctlr->amp == nil)
|
getoutamp(ctlr->amp, a);
|
||||||
return -1;
|
|
||||||
qlock(ctlr);
|
|
||||||
getoutamp(ctlr->amp, a);
|
|
||||||
qunlock(ctlr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,24 +1110,32 @@ static int
|
||||||
hdasetvol(Audio *adev, int, int a[2])
|
hdasetvol(Audio *adev, int, int a[2])
|
||||||
{
|
{
|
||||||
Ctlr *ctlr = adev->ctlr;
|
Ctlr *ctlr = adev->ctlr;
|
||||||
|
if(ctlr->amp != nil)
|
||||||
if(ctlr->amp == nil)
|
setoutamp(ctlr->amp, 0, a);
|
||||||
return -1;
|
|
||||||
qlock(ctlr);
|
|
||||||
setoutamp(ctlr->amp, 0, a[0]);
|
|
||||||
qunlock(ctlr);
|
|
||||||
return 0;
|
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
|
static long
|
||||||
hdavolread(Audio *adev, void *a, long n, vlong)
|
hdavolread(Audio *adev, void *a, long n, vlong)
|
||||||
{
|
{
|
||||||
|
Volume voltab[2];
|
||||||
|
fillvoltab(adev->ctlr, voltab);
|
||||||
return genaudiovolread(adev, a, n, 0, voltab, hdagetvol, 0);
|
return genaudiovolread(adev, a, n, 0, voltab, hdagetvol, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
hdavolwrite(Audio *adev, void *a, long n, vlong)
|
hdavolwrite(Audio *adev, void *a, long n, vlong)
|
||||||
{
|
{
|
||||||
|
Volume voltab[2];
|
||||||
|
fillvoltab(adev->ctlr, voltab);
|
||||||
return genaudiovolwrite(adev, a, n, 0, voltab, hdasetvol, 0);
|
return genaudiovolwrite(adev, a, n, 0, voltab, hdasetvol, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1264,6 +1270,45 @@ hdamatch(Pcidev *p)
|
||||||
return nil;
|
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; i<n/4; i++){
|
||||||
|
if(hdacmd(ctlr, lp[i], w) < 0){
|
||||||
|
w[0] = 0;
|
||||||
|
w[1] = ~0;
|
||||||
|
}
|
||||||
|
qproduce(ctlr->q, w, sizeof(w));
|
||||||
|
}
|
||||||
|
qunlock(ctlr);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hdareset(Audio *adev)
|
hdareset(Audio *adev)
|
||||||
{
|
{
|
||||||
|
@ -1304,6 +1349,7 @@ Found:
|
||||||
|
|
||||||
ctlr->no = adev->ctlrno;
|
ctlr->no = adev->ctlrno;
|
||||||
ctlr->size = p->mem[0].size;
|
ctlr->size = p->mem[0].size;
|
||||||
|
ctlr->q = qopen(256, 0, 0, 0);
|
||||||
ctlr->mem = vmap(p->mem[0].bar & ~0x0F, ctlr->size);
|
ctlr->mem = vmap(p->mem[0].bar & ~0x0F, ctlr->size);
|
||||||
if(ctlr->mem == nil){
|
if(ctlr->mem == nil){
|
||||||
print("#A%d: can't map %.8lux\n", ctlr->no, p->mem[0].bar);
|
print("#A%d: can't map %.8lux\n", ctlr->no, p->mem[0].bar);
|
||||||
|
@ -1345,6 +1391,8 @@ Found:
|
||||||
adev->ctl = hdactl;
|
adev->ctl = hdactl;
|
||||||
|
|
||||||
intrenable(irq, hdainterrupt, adev, tbdf, "hda");
|
intrenable(irq, hdainterrupt, adev, tbdf, "hda");
|
||||||
|
lastcard = ctlr;
|
||||||
|
addarchfile("hdacmd", 0664, hdacmdread, hdacmdwrite);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1354,3 +1402,4 @@ audiohdalink(void)
|
||||||
{
|
{
|
||||||
addaudiocard("hda", hdareset);
|
addaudiocard("hda", hdareset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,17 @@ enum {
|
||||||
KbdCSP = 0x010103, /* keyboard.boot.hid */
|
KbdCSP = 0x010103, /* keyboard.boot.hid */
|
||||||
|
|
||||||
/* Requests */
|
/* Requests */
|
||||||
|
Getreport = 0x01,
|
||||||
|
Setreport = 0x09,
|
||||||
Getproto = 0x03,
|
Getproto = 0x03,
|
||||||
Setproto = 0x0b,
|
Setproto = 0x0b,
|
||||||
|
|
||||||
/* protocols for SET_PROTO request */
|
/* protocols for SET_PROTO request */
|
||||||
Bootproto = 0,
|
Bootproto = 0,
|
||||||
Reportproto = 1,
|
Reportproto = 1,
|
||||||
|
|
||||||
|
/* protocols for SET_REPORT request */
|
||||||
|
Reportout = 0x0200,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -124,6 +124,12 @@ setbootproto(KDev* f, int eid)
|
||||||
return usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0);
|
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.
|
* 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.
|
* 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;
|
kd->ep = nil;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(setleds(kd, ep->id, 0) < 0){
|
||||||
|
fprint(2, "kb: %s: setleds: %r\n", d->dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
incref(d);
|
incref(d);
|
||||||
proccreate(f, kd, Stack);
|
proccreate(f, kd, Stack);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue