ref: f649ceba09da8dc38ed53f2a8f5e89bb3848c1bd
parent: f64e8a1c84a7905884a1c743cab23ce295209e96
author: cinap_lenrek <[email protected]>
date: Sun Mar 4 01:17:40 EST 2012
audiohda: set power state, eapd for x61
--- a/sys/src/9/pc/audiohda.c
+++ b/sys/src/9/pc/audiohda.c
@@ -146,6 +146,7 @@
Pin = 1<<5,
Pbalanced = 1<<6,
Phdmi = 1<<7,
+ Peapd = 1<<16,
Inampcap = 0x0d,
Outampcap = 0x12,
Connlistlen = 0x0e,
@@ -158,6 +159,8 @@
Getconnlist = 0xf02,
Getstate = 0xf03,
Setstate = 0x703,
+ Setpower = 0x705,
+ Getpower = 0xf05,
Getstream = 0xf06,
Setstream = 0x706,
Getpinctl = 0xf07,
@@ -164,6 +167,7 @@
Setpinctl = 0x707,
Pinctlin = 1<<5,
Pinctlout = 1<<6,
+ Pinctlhphn = 1<<7,
Getunsolresp = 0xf08,
Setunsolresp = 0x708,
Getpinsense = 0xf09,
@@ -172,6 +176,10 @@
Setgpi = 0x710,
Getbeep = 0xf0a,
Setbeep = 0x70a,
+ Seteapd = 0x70c,
+ Btlenable = 1,
+ Eapdenable = 2,
+ LRswap = 4,
Getknob = 0xf0f,
Setknob = 0x70f,
Getdefault = 0xf1c,
@@ -311,6 +319,17 @@
#define csr16(c, r) (*(ushort *)&(c)->mem[r])
#define csr8(c, r) (*(uchar *)&(c)->mem[r])
+static char *widtype[] = {
+ "aout",
+ "ain",
+ "amix",
+ "asel",
+ "pin",
+ "power",
+ "knob",
+ "beep",
+};
+
static char *pinport[] = {
"jack",
"nothing",
@@ -590,33 +609,25 @@
}
static void
-connectpath(Widget *src, Widget *dst, uint stream)
+connectpath(Widget *src, Widget *dst)
{
Widget *w, *v;
uint i;
- for(w=src->fg->first; w != nil; w=w->next){
- 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, nil);
setinamp(v, w, 0, nil);
- if(v->type == Waout || v->type == Wamix)
- continue;
if(v->nlist == 1)
continue;
- for(i=0; i < v->nlist && v->list[i] != w; i++)
- ;
- cmd(v->id, Setconn, i);
+ for(i=0; i < v->nlist; i++)
+ if(v->list[i] == w){
+ cmd(v->id, Setconn, i);
+ break;
+ }
}
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);
- cmd(dst->id, Setchancnt, 1);
+ cmd(src, Setpinctl, Pinctlout);
}
static void
@@ -624,13 +635,14 @@
{
Widget *src;
- if(nid >= Maxwidgets)
- return;
- if((src = w->fg->codec->widgets[nid]) == nil)
- return;
- for(nid=0; nid<w->nlist; nid++)
- if(w->list[nid] == src)
- return;
+ src = nil;
+ if(nid < Maxwidgets)
+ src = w->fg->codec->widgets[nid];
+ if(src == nil || (src->fg != w->fg)){
+ print("hda: invalid connection %d:%s[%d] -> %d\n",
+ w->id.nid, widtype[w->type & 7], w->nlist, nid);
+ src = nil;
+ }
if((w->nlist % 16) == 0){
void *p;
@@ -641,6 +653,7 @@
w->list = p;
}
w->list[w->nlist++] = src;
+ return;
}
static void
@@ -648,6 +661,9 @@
{
uint r, f, b, m, i, n, x, y;
+ if((w->cap & Wconncap) == 0)
+ return;
+
r = cmd(w->id, Getparm, Connlistlen);
n = r & 0x7f;
b = (r & 0x80) ? 16 : 8;
@@ -660,7 +676,7 @@
else
r = cmd(w->id, Getconnlist, i);
y = r & (m>>1);
- if(i && ((r & m) != y))
+ if(i && (r & m) != y)
while(++x < y)
addconn(w, x);
addconn(w, y);
@@ -673,6 +689,8 @@
{
w->cap = cmd(w->id, Getparm, Widgetcap);
w->type = (w->cap >> 20) & 0x7;
+ if(w->cap & Wpwrcap)
+ cmd(w->id, Setpower, 0);
enumconns(w);
@@ -680,6 +698,8 @@
case Wpin:
w->pin = cmd(w->id, Getdefault, 0);
w->pincap = cmd(w->id, Getparm, Pincap);
+ if(w->pincap & Peapd)
+ cmd(w->id, Seteapd, Eapdenable);
break;
}
}
@@ -692,9 +712,15 @@
uint i, r, n, base;
r = cmd(id, Getparm, Fungrtype) & 0x7f;
- if(r != Graudio)
+ if(r != Graudio){
+ cmd(id, Setpower, 3); /* turn off */
return nil;
+ }
+ /* open eyes */
+ cmd(id, Setpower, 0);
+ microdelay(100);
+
fg = mallocz(sizeof *fg, 1);
if(fg == nil){
Nomem:
@@ -728,9 +754,9 @@
}
w->id = newnid(id, base + i);
w->fg = fg;
- codec->widgets[base + i] = w;
*tail = w;
tail = &w->next;
+ codec->widgets[w->id.nid] = w;
}
for(i=0; i<n; i++)
@@ -756,9 +782,6 @@
codec->vid = vid;
codec->rid = rid;
- print("#A%d: codec #%d, vendor %08x, rev %08x\n",
- id.ctlr->no, codec->id.codec, codec->vid, codec->rid);
-
r = cmd(id, Getparm, Subnodecnt);
n = r & 0xff;
base = (r >> 16) & 0xff;
@@ -772,6 +795,10 @@
}
if(codec->fgroup == nil)
return -1;
+
+ print("#A%d: codec #%d, vendor %08x, rev %08x\n",
+ id.ctlr->no, codec->id.codec, codec->vid, codec->rid);
+
return 0;
}
@@ -809,7 +836,7 @@
static int
connectpin(Ctlr *ctlr, uint pin, uint cad)
{
- Widget *src, *dst;
+ Widget *w, *src, *dst;
if(cad >= Maxcodecs || pin >= Maxwidgets || ctlr->codec[cad] == nil)
return -1;
@@ -820,10 +847,24 @@
return -1;
if((src->pincap & Pout) == 0)
return -1;
+
dst = findpath(src);
if(!dst)
return -1;
- connectpath(src, dst, ctlr->atag);
+
+ /* 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);
+ }
+
+ connectpath(src, dst);
+
+ cmd(dst->id, Setconvfmt, ctlr->afmt);
+ cmd(dst->id, Setstream, (ctlr->atag << 4) | 0);
+ cmd(dst->id, Setchancnt, 1);
+
ctlr->amp = dst;
ctlr->src = src;
ctlr->pin = pin;
@@ -1245,7 +1286,7 @@
if(w->type != Wpin)
continue;
r = w->pin;
- k += snprint(s+k, n-k, "pin %3d %s %s %s %s %s %s\n",
+ k += snprint(s+k, n-k, "pin %3d %s %s %s %s %s %s%s%s\n",
w->id.nid,
(w->pincap & Pout) != 0 ? "out" : "in",
pinport[(r >> 30) & 0x3],
@@ -1252,7 +1293,9 @@
pinloc2[(r >> 28) & 0x3],
pinloc[(r >> 24) & 0xf],
pinfunc[(r >> 20) & 0xf],
- pincol[(r >> 12) & 0xf]
+ pincol[(r >> 12) & 0xf],
+ (w->pincap & Phdmi) ? " hdmi" : "",
+ (w->pincap & Peapd) ? " eapd" : ""
);
}
}