2 #include "../port/lib.h"
7 #include "../port/error.h"
8 #include "../port/audio.h"
10 typedef ushort (*ac97rdfn)(Audio *, int);
11 typedef void (*ac97wrfn)(Audio *, int, ushort);
13 typedef struct Mixer Mixer;
14 typedef struct Volume Volume;
23 enum { Maxbusywait = 500000 };
75 Extiddsa0 = 0<<4, /* extid only */
76 Extiddsa1 = 1<<4, /* extid only */
77 Extiddsa2 = 2<<4, /* extid only */
78 Extiddsa3 = 3<<4, /* extid only */
79 Extcsrspsa34 = 0<<4, /* extcsr only */
80 Extcsrspsa78 = 1<<4, /* extcsr only */
81 Extcsrspsa69 = 2<<4, /* extcsr only */
82 ExtcsrspsaAB = 3<<4, /* extcsr only */
86 Extidamap = 1<<9, /* extid only */
87 Extidrev11 = 0<<10, /* extid only */
88 Extidrev22 = 1<<10, /* extid only */
89 Extidrev23 = 2<<10, /* extid only */
90 Extidprim = 0<<14, /* extid only */
91 Extidsec0 = 1<<14, /* extid only */
92 Extidsec1 = 2<<14, /* extid only */
93 Extidsec2 = 3<<14, /* extid only */
94 Extcsrmadc = 1<<9, /* extcsr only */
95 Extcsrspcv = 1<<10, /* extcsr only */
96 Extcsrpri = 1<<11, /* extcsr only */
97 Extcsrprj = 1<<12, /* extcsr only */
98 Extcsrprk = 1<<13, /* extcsr only */
99 Extcsrprl = 1<<14, /* extcsr only */
100 Extcsrvcfg = 1<<15, /* extcsr only */
101 Pcmfrontdacrate = 0x2C,
102 Pcmsurrounddacrate = 0x2E,
103 Pcmlfedacrate = 0x30,
105 Pcmmicadcrate = 0x34,
110 Spdifnonaudio = 1<<1,
163 [Vmaster] {Master, 63, Stereo, 0, "master"},
164 [Vaudio] {Pcmout, 31, Stereo, 0, "audio"},
165 [Vhead] {Headphone, 31, Stereo, Capheadphones, "head"},
166 [Vbass] {Mastertone, 15, Left, Captonectl, "bass"},
167 [Vtreb] {Mastertone, 15, Right, Captonectl, "treb"},
168 [Vbeep] {Pcbeep, 31, Right, 0, "beep"},
169 [Vphone] {Phone, 31, Right, 0, "phone"},
170 [Vmic] {Mic, 31, Right, Capmic, "mic"},
171 [Vline] {Line, 31, Stereo, 0, "line"},
172 [Vcd] {Cd, 31, Stereo, 0, "cd"},
173 [Vvideo] {Video, 31, Stereo, 0, "video"},
174 [Vaux] {Aux, 63, Stereo, 0, "aux"},
175 [Vrecgain] {Recgain, 15, Stereo, 0, "recgain"},
176 [Vmicgain] {Micgain, 15, Right, Capmic, "micgain"},
181 ac97mixtopology(Audio *adev, void *a, long n, vlong off)
189 caps = m->rr(adev, Reset);
190 caps |= m->rr(adev, Extid) << 16;
192 buf = malloc(READSTR);
193 l += snprint(buf+l, READSTR-l, "not implemented. have fun.\n");
197 n = readstr(off, a, n, buf);
203 ac97mixread(Audio *adev, void *a, long n, vlong off)
211 buf = malloc(READSTR);
215 caps = m->rr(adev, Reset);
216 caps |= m->rr(adev, Extid) << 16;
217 for(i = 0; vol[i].name != 0; ++i){
218 if(vol[i].cap && ((vol[i].cap & caps) == 0))
220 v = m->rr(adev, vol[i].reg);
223 if(vol[i].type == Absolute){
224 l += snprint(buf+l, READSTR-l, "%s %d", nam, v);
226 ri = ((rang-(v&rang)) * 100) / rang;
227 le = ((rang-((v>>8)&rang)) * 100) / rang;
228 if(vol[i].type == Stereo)
229 l += snprint(buf+l, READSTR-l, "%s %d %d", nam, le, ri);
230 if(vol[i].type == Left)
231 l += snprint(buf+l, READSTR-l, "%s %d", nam, le);
232 if(vol[i].type == Right)
233 l += snprint(buf+l, READSTR-l, "%s %d", nam, ri);
235 l += snprint(buf+l, READSTR-l, " mute");
237 l += snprint(buf+l, READSTR-l, "\n");
240 n = readstr(off, a, n, buf);
246 ac97mixwrite(Audio *adev, void *a, long n, vlong)
250 int ntok, i, left, right, rang, reg;
254 ntok = tokenize(a, tok, 4);
255 for(i = 0; vol[i].name != 0; ++i){
256 if(!strcmp(vol[i].name, tok[0])){
261 left = right = atoi(tok[1]);
263 right = atoi(tok[2]);
265 if(vol[i].type == Absolute){
266 m->wr(adev, reg, left);
268 left = rang - ((left*rang)) / 100;
269 right = rang - ((right*rang)) / 100;
274 v = m->rr(adev, reg);
275 v = (v & 0x007f) | (left << 8);
279 v = m->rr(adev, reg);
280 v = (v & 0x7f00) | right;
284 v = (left<<8) | right;
293 if(vol[i].name == nil){
295 for(p = tok[0]; *p; ++p)
296 if(*p < '0' || *p > '9') {
298 error("no such volume setting");
302 left = right = rang - ((atoi(tok[0])*rang)) / 100;
303 v = (left<<8) | right;
312 ac97hardrate(Audio *adev, int rate)
317 oldrate = m->rr(adev, Pcmfrontdacrate);
319 m->wr(adev, Pcmfrontdacrate, rate);
324 ac97mixreset(Audio *adev, ac97wrfn wr, ac97rdfn rr)
329 if(adev->mixer == nil)
330 adev->mixer = malloc(sizeof(Mixer));
334 adev->volread = ac97mixread;
335 adev->volwrite = ac97mixwrite;
336 m->wr(adev, Reset, 0);
337 m->wr(adev, Powerdowncsr, 0);
339 t = (Adcpower | Dacpower | Anlpower | Refpower);
340 for(i = 0; i < Maxbusywait; i++){
341 if((m->rr(adev, Powerdowncsr) & t) == t)
346 print("#A%d: ac97 exhausted waiting powerup\n", adev->ctlrno);
348 t = m->rr(adev, Extid);
349 print("#A%d: ac97 codec ext:%s%s%s%s%s%s%s\n", adev->ctlrno,
350 (t & Extvra) ? " vra" : "",
351 (t & Extdra) ? " dra" : "",
352 (t & Extspdif) ? " spdif" : "",
353 (t & Extvrm) ? " vrm" : "",
354 (t & Extcdac) ? " cdac" : "",
355 (t & Extsdac) ? " sdac" : "",
356 (t & Extldac) ? " ldac" : "");
359 m->wr(adev, Extcsr, Extvra);
362 print("#A%d: ac97 vra extension not supported\n", adev->ctlrno);