2 #include "../port/lib.h"
7 #include "../port/error.h"
8 #include "../port/audioif.h"
10 enum { Maxbusywait = 500000 };
48 Extiddsa0 = 0<<4, /* extid only */
49 Extiddsa1 = 1<<4, /* extid only */
50 Extiddsa2 = 2<<4, /* extid only */
51 Extiddsa3 = 3<<4, /* extid only */
52 Extcsrspsa34 = 0<<4, /* extcsr only */
53 Extcsrspsa78 = 1<<4, /* extcsr only */
54 Extcsrspsa69 = 2<<4, /* extcsr only */
55 ExtcsrspsaAB = 3<<4, /* extcsr only */
59 Extidamap = 1<<9, /* extid only */
60 Extidrev11 = 0<<10, /* extid only */
61 Extidrev22 = 1<<10, /* extid only */
62 Extidrev23 = 2<<10, /* extid only */
63 Extidprim = 0<<14, /* extid only */
64 Extidsec0 = 1<<14, /* extid only */
65 Extidsec1 = 2<<14, /* extid only */
66 Extidsec2 = 3<<14, /* extid only */
67 Extcsrmadc = 1<<9, /* extcsr only */
68 Extcsrspcv = 1<<10, /* extcsr only */
69 Extcsrpri = 1<<11, /* extcsr only */
70 Extcsrprj = 1<<12, /* extcsr only */
71 Extcsrprk = 1<<13, /* extcsr only */
72 Extcsrprl = 1<<14, /* extcsr only */
73 Extcsrvcfg = 1<<15, /* extcsr only */
74 Pcmfrontdacrate = 0x2C,
75 Pcmsurrounddacrate = 0x2E,
116 static Volume voltab[] = {
117 [Vmaster] "master", 0x02, -63, Stereo, 0,
118 [Vaudio] "audio", 0x18, -31, Stereo, 0,
119 [Vhead] "head", 0x04, -31, Stereo, Capheadphones,
120 [Vbass] "bass", 0x08, 15, Left, Captonectl,
121 [Vtreb] "treb", 0x08, 15, Right, Captonectl,
122 [Vbeep] "beep", 0x0a, -31, Right, 0,
123 [Vphone] "phone", 0x0c, -31, Right, 0,
124 [Vmic] "mic", 0x0e, -31, Right, Capmic,
125 [Vline] "line", 0x10, -31, Stereo, 0,
126 [Vcd] "cd", 0x12, -31, Stereo, 0,
127 [Vvideo] "video", 0x14, -31, Stereo, 0,
128 [Vaux] "aux", 0x16, -63, Stereo, 0,
129 [Vrecgain] "recgain", 0x1c, 15, Stereo, 0,
130 [Vmicgain] "micgain", 0x1e, 15, Right, Capmic,
131 [Vspeed] "speed", 0x2c, 0, Absolute, 0,
132 [Vdelay] "delay", 0, 0, Absolute, 0,
136 typedef struct Mixer Mixer;
139 ushort (*rr)(Audio *, int);
140 void (*wr)(Audio *, int, ushort);
145 ac97volget(Audio *adev, int x, int a[2])
147 Mixer *m = adev->mixer;
158 a[0] = m->rr(adev, vol->reg);
161 v = m->rr(adev, vol->reg);
163 a[0] = a[1] = vol->range < 0 ? 0x7f : 0;
165 a[0] = ((v>>8) & 0x7f);
173 ac97volset(Audio *adev, int x, int a[2])
175 Mixer *m = adev->mixer;
186 m->wr(adev, vol->reg, a[0]);
188 m->wr(adev, 0x32, a[0]); /* adc rate */
189 adev->speed = m->rr(adev, vol->reg);
194 w = m->rr(adev, vol->reg) & 0x7f;
195 m->wr(adev, vol->reg, (v<<8)|w);
198 v = m->rr(adev, vol->reg) & 0x7f00;
200 m->wr(adev, vol->reg, v|w);
205 m->wr(adev, vol->reg, (v<<8)|w);
213 ac97mixread(Audio *adev, void *a, long n, vlong)
215 Mixer *m = adev->mixer;
218 caps = m->rr(adev, Reset);
219 caps |= m->rr(adev, Extid) << 16;
220 return genaudiovolread(adev, a, n, 0, voltab, ac97volget, caps);
224 ac97mixwrite(Audio *adev, void *a, long n, vlong)
226 Mixer *m = adev->mixer;
229 caps = m->rr(adev, Reset);
230 caps |= m->rr(adev, Extid) << 16;
231 return genaudiovolwrite(adev, a, n, 0, voltab, ac97volset, caps);
235 ac97mixreset(Audio *adev, void (*wr)(Audio*,int,ushort), ushort (*rr)(Audio*,int))
241 m = malloc(sizeof(Mixer));
243 print("ac97mix: no memory for Mixer\n");
248 m->wr(adev, Reset, 0);
249 m->wr(adev, Powerdowncsr, 0);
251 t = (Adcpower | Dacpower | Anlpower | Refpower);
252 for(i = 0; i < Maxbusywait; i++){
253 if((m->rr(adev, Powerdowncsr) & t) == t)
258 print("#A%d: ac97 exhausted waiting powerup\n", adev->ctlrno);
260 t = m->rr(adev, Extid);
261 print("#A%d: ac97 codec ext:%s%s%s%s%s%s%s\n", adev->ctlrno,
262 (t & Extvra) ? " vra" : "",
263 (t & Extdra) ? " dra" : "",
264 (t & Extspdif) ? " spdif" : "",
265 (t & Extvrm) ? " vrm" : "",
266 (t & Extcdac) ? " cdac" : "",
267 (t & Extsdac) ? " sdac" : "",
268 (t & Extldac) ? " ldac" : "");
271 m->wr(adev, Extcsr, Extvra);
274 print("#A%d: ac97 vra extension not supported\n", adev->ctlrno);
279 adev->volread = ac97mixread;
280 adev->volwrite = ac97mixwrite;