FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/pcm/ac97.c
1 /*-
2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <dev/sound/pcm/sound.h>
28 #include <dev/sound/pcm/ac97.h>
29 #include <dev/sound/pcm/ac97_patch.h>
30
31 #include <dev/pci/pcivar.h>
32
33 #include "mixer_if.h"
34
35 SND_DECLARE_FILE("$FreeBSD$");
36
37 MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
38
39 struct ac97mixtable_entry {
40 int reg; /* register index */
41 /* reg < 0 if inverted polarity */
42 unsigned bits:4; /* width of control field */
43 unsigned ofs:4; /* offset (only if stereo=0) */
44 unsigned stereo:1; /* set for stereo controls */
45 unsigned mute:1; /* bit15 is MUTE */
46 unsigned recidx:4; /* index in rec mux */
47 unsigned mask:1; /* use only masked bits */
48 unsigned enable:1; /* entry is enabled */
49 };
50
51 #define AC97_MIXER_SIZE SOUND_MIXER_NRDEVICES
52
53 struct ac97_info {
54 kobj_t methods;
55 device_t dev;
56 void *devinfo;
57 u_int32_t id;
58 u_int32_t subvendor;
59 unsigned count, caps, se, extcaps, extid, extstat, noext:1;
60 u_int32_t flags;
61 struct ac97mixtable_entry mix[AC97_MIXER_SIZE];
62 char name[16];
63 struct mtx *lock;
64 };
65
66 struct ac97_vendorid {
67 u_int32_t id;
68 const char *name;
69 };
70
71 struct ac97_codecid {
72 u_int32_t id;
73 u_int8_t stepmask;
74 u_int8_t noext:1;
75 char *name;
76 ac97_patch patch;
77 };
78
79 static const struct ac97mixtable_entry ac97mixtable_default[AC97_MIXER_SIZE] = {
80 /* [offset] reg bits of st mu re mk en */
81 [SOUND_MIXER_VOLUME] = { AC97_MIX_MASTER, 5, 0, 1, 1, 6, 0, 1 },
82 [SOUND_MIXER_OGAIN] = { AC97_MIX_AUXOUT, 5, 0, 1, 1, 0, 0, 0 },
83 [SOUND_MIXER_PHONEOUT] = { AC97_MIX_MONO, 5, 0, 0, 1, 7, 0, 0 },
84 [SOUND_MIXER_BASS] = { AC97_MIX_TONE, 4, 8, 0, 0, 0, 1, 0 },
85 [SOUND_MIXER_TREBLE] = { AC97_MIX_TONE, 4, 0, 0, 0, 0, 1, 0 },
86 [SOUND_MIXER_PCM] = { AC97_MIX_PCM, 5, 0, 1, 1, 0, 0, 1 },
87 [SOUND_MIXER_SPEAKER] = { AC97_MIX_BEEP, 4, 1, 0, 1, 0, 0, 0 },
88 [SOUND_MIXER_LINE] = { AC97_MIX_LINE, 5, 0, 1, 1, 5, 0, 1 },
89 [SOUND_MIXER_PHONEIN] = { AC97_MIX_PHONE, 5, 0, 0, 1, 8, 0, 0 },
90 [SOUND_MIXER_MIC] = { AC97_MIX_MIC, 5, 0, 0, 1, 1, 1, 1 },
91 /* use igain for the mic 20dB boost */
92 [SOUND_MIXER_IGAIN] = { -AC97_MIX_MIC, 1, 6, 0, 0, 0, 1, 1 },
93 [SOUND_MIXER_CD] = { AC97_MIX_CD, 5, 0, 1, 1, 2, 0, 1 },
94 [SOUND_MIXER_LINE1] = { AC97_MIX_AUX, 5, 0, 1, 1, 4, 0, 0 },
95 [SOUND_MIXER_VIDEO] = { AC97_MIX_VIDEO, 5, 0, 1, 1, 3, 0, 0 },
96 [SOUND_MIXER_RECLEV] = { -AC97_MIX_RGAIN, 4, 0, 1, 1, 0, 0, 1 }
97 };
98
99 static const struct ac97_vendorid ac97vendorid[] = {
100 { 0x41445300, "Analog Devices" },
101 { 0x414b4d00, "Asahi Kasei" },
102 { 0x414c4300, "Realtek" },
103 { 0x414c4700, "Avance Logic" },
104 { 0x43525900, "Cirrus Logic" },
105 { 0x434d4900, "C-Media Electronics" },
106 { 0x43585400, "Conexant" },
107 { 0x44543000, "Diamond Technology" },
108 { 0x454d4300, "eMicro" },
109 { 0x45838300, "ESS Technology" },
110 { 0x48525300, "Intersil" },
111 { 0x49434500, "ICEnsemble" },
112 { 0x49544500, "ITE, Inc." },
113 { 0x4e534300, "National Semiconductor" },
114 { 0x50534300, "Philips Semiconductor" },
115 { 0x83847600, "SigmaTel" },
116 { 0x53494c00, "Silicon Laboratories" },
117 { 0x54524100, "TriTech" },
118 { 0x54584e00, "Texas Instruments" },
119 { 0x56494100, "VIA Technologies" },
120 { 0x57454300, "Winbond" },
121 { 0x574d4c00, "Wolfson" },
122 { 0x594d4800, "Yamaha" },
123 /*
124 * XXX This is a fluke, really! The real vendor
125 * should be SigmaTel, not this! This should be
126 * removed someday!
127 */
128 { 0x01408300, "Creative" },
129 { 0x00000000, NULL }
130 };
131
132 static struct ac97_codecid ac97codecid[] = {
133 { 0x41445303, 0x00, 0, "AD1819", 0 },
134 { 0x41445340, 0x00, 0, "AD1881", 0 },
135 { 0x41445348, 0x00, 0, "AD1881A", 0 },
136 { 0x41445360, 0x00, 0, "AD1885", 0 },
137 { 0x41445361, 0x00, 0, "AD1886", ad1886_patch },
138 { 0x41445362, 0x00, 0, "AD1887", 0 },
139 { 0x41445363, 0x00, 0, "AD1886A", 0 },
140 { 0x41445368, 0x00, 0, "AD1888", ad198x_patch },
141 { 0x41445370, 0x00, 0, "AD1980", ad198x_patch },
142 { 0x41445372, 0x00, 0, "AD1981A", 0 },
143 { 0x41445374, 0x00, 0, "AD1981B", ad1981b_patch },
144 { 0x41445375, 0x00, 0, "AD1985", ad198x_patch },
145 { 0x41445378, 0x00, 0, "AD1986", ad198x_patch },
146 { 0x414b4d00, 0x00, 1, "AK4540", 0 },
147 { 0x414b4d01, 0x00, 1, "AK4542", 0 },
148 { 0x414b4d02, 0x00, 1, "AK4543", 0 },
149 { 0x414b4d06, 0x00, 0, "AK4544A", 0 },
150 { 0x454b4d07, 0x00, 0, "AK4545", 0 },
151 { 0x414c4320, 0x0f, 0, "ALC100", 0 },
152 { 0x414c4730, 0x0f, 0, "ALC101", 0 },
153 { 0x414c4710, 0x0f, 0, "ALC200", 0 },
154 { 0x414c4740, 0x0f, 0, "ALC202", 0 },
155 { 0x414c4720, 0x0f, 0, "ALC650", 0 },
156 { 0x414c4752, 0x0f, 0, "ALC250", 0 },
157 { 0x414c4760, 0x0f, 0, "ALC655", alc655_patch },
158 { 0x414c4770, 0x0f, 0, "ALC203", 0 },
159 { 0x414c4780, 0x0f, 0, "ALC658", 0 },
160 { 0x414c4790, 0x0f, 0, "ALC850", 0 },
161 { 0x43525900, 0x07, 0, "CS4297", 0 },
162 { 0x43525910, 0x07, 0, "CS4297A", 0 },
163 { 0x43525920, 0x07, 0, "CS4294/98", 0 },
164 { 0x4352592d, 0x07, 0, "CS4294", 0 },
165 { 0x43525930, 0x07, 0, "CS4299", 0 },
166 { 0x43525940, 0x07, 0, "CS4201", 0 },
167 { 0x43525958, 0x07, 0, "CS4205", 0 },
168 { 0x43525960, 0x07, 0, "CS4291A", 0 },
169 { 0x434d4961, 0x00, 0, "CMI9739", cmi9739_patch },
170 { 0x434d4941, 0x00, 0, "CMI9738", 0 },
171 { 0x434d4978, 0x00, 0, "CMI9761", 0 },
172 { 0x434d4982, 0x00, 0, "CMI9761", 0 },
173 { 0x434d4983, 0x00, 0, "CMI9761", 0 },
174 { 0x43585421, 0x00, 0, "HSD11246", 0 },
175 { 0x43585428, 0x07, 0, "CX20468", 0 },
176 { 0x43585430, 0x00, 0, "CX20468-21", 0 },
177 { 0x44543000, 0x00, 0, "DT0398", 0 },
178 { 0x454d4323, 0x00, 0, "EM28023", 0 },
179 { 0x454d4328, 0x00, 0, "EM28028", 0 },
180 { 0x45838308, 0x00, 0, "ES1988", 0 }, /* Formerly ES1921(?) */
181 { 0x48525300, 0x00, 0, "HMP9701", 0 },
182 { 0x49434501, 0x00, 0, "ICE1230", 0 },
183 { 0x49434511, 0x00, 0, "ICE1232", 0 },
184 { 0x49434514, 0x00, 0, "ICE1232A", 0 },
185 { 0x49434551, 0x03, 0, "VT1616", 0 }, /* Via badged ICE */
186 { 0x49544520, 0x00, 0, "ITE2226E", 0 },
187 { 0x49544560, 0x07, 0, "ITE2646E", 0 }, /* XXX: patch needed */
188 { 0x4e534340, 0x00, 0, "LM4540", 0 }, /* Spec blank on revid */
189 { 0x4e534343, 0x00, 0, "LM4543", 0 }, /* Ditto */
190 { 0x4e534346, 0x00, 0, "LM4546A", 0 },
191 { 0x4e534348, 0x00, 0, "LM4548A", 0 },
192 { 0x4e534331, 0x00, 0, "LM4549", 0 },
193 { 0x4e534349, 0x00, 0, "LM4549A", 0 },
194 { 0x4e534350, 0x00, 0, "LM4550", 0 },
195 { 0x50534301, 0x00, 0, "UCB1510", 0 },
196 { 0x50534304, 0x00, 0, "UCB1400", 0 },
197 { 0x83847600, 0x00, 0, "STAC9700/83/84", 0 },
198 { 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 },
199 { 0x83847605, 0x00, 0, "STAC9704", 0 },
200 { 0x83847608, 0x00, 0, "STAC9708/11", 0 },
201 { 0x83847609, 0x00, 0, "STAC9721/23", 0 },
202 { 0x83847644, 0x00, 0, "STAC9744/45", 0 },
203 { 0x83847650, 0x00, 0, "STAC9750/51", 0 },
204 { 0x83847652, 0x00, 0, "STAC9752/53", 0 },
205 { 0x83847656, 0x00, 0, "STAC9756/57", 0 },
206 { 0x83847658, 0x00, 0, "STAC9758/59", 0 },
207 { 0x83847660, 0x00, 0, "STAC9760/61", 0 }, /* Extrapolated */
208 { 0x83847662, 0x00, 0, "STAC9762/63", 0 }, /* Extrapolated */
209 { 0x83847666, 0x00, 0, "STAC9766/67", 0 },
210 { 0x53494c22, 0x00, 0, "Si3036", 0 },
211 { 0x53494c23, 0x00, 0, "Si3038", 0 },
212 { 0x54524103, 0x00, 0, "TR28023", 0 }, /* Extrapolated */
213 { 0x54524106, 0x00, 0, "TR28026", 0 },
214 { 0x54524108, 0x00, 0, "TR28028", 0 },
215 { 0x54524123, 0x00, 0, "TR28602", 0 },
216 { 0x54524e03, 0x07, 0, "TLV320AIC27", 0 },
217 { 0x54584e20, 0x00, 0, "TLC320AD90", 0 },
218 { 0x56494161, 0x00, 0, "VIA1612A", 0 },
219 { 0x56494170, 0x00, 0, "VIA1617A", 0 },
220 { 0x574d4c00, 0x00, 0, "WM9701A", 0 },
221 { 0x574d4c03, 0x00, 0, "WM9703/4/7/8", 0 },
222 { 0x574d4c04, 0x00, 0, "WM9704Q", 0 },
223 { 0x574d4c05, 0x00, 0, "WM9705/10", 0 },
224 { 0x574d4d09, 0x00, 0, "WM9709", 0 },
225 { 0x574d4c12, 0x00, 0, "WM9711/12", 0 }, /* XXX: patch needed */
226 { 0x57454301, 0x00, 0, "W83971D", 0 },
227 { 0x594d4800, 0x00, 0, "YMF743", 0 },
228 { 0x594d4802, 0x00, 0, "YMF752", 0 },
229 { 0x594d4803, 0x00, 0, "YMF753", 0 },
230 /*
231 * XXX This is a fluke, really! The real codec
232 * should be STAC9704, not this! This should be
233 * removed someday!
234 */
235 { 0x01408384, 0x00, 0, "EV1938", 0 },
236 { 0, 0, 0, NULL, 0 }
237 };
238
239 static char *ac97enhancement[] = {
240 "no 3D Stereo Enhancement",
241 "Analog Devices Phat Stereo",
242 "Creative Stereo Enhancement",
243 "National Semi 3D Stereo Enhancement",
244 "Yamaha Ymersion",
245 "BBE 3D Stereo Enhancement",
246 "Crystal Semi 3D Stereo Enhancement",
247 "Qsound QXpander",
248 "Spatializer 3D Stereo Enhancement",
249 "SRS 3D Stereo Enhancement",
250 "Platform Tech 3D Stereo Enhancement",
251 "AKM 3D Audio",
252 "Aureal Stereo Enhancement",
253 "Aztech 3D Enhancement",
254 "Binaura 3D Audio Enhancement",
255 "ESS Technology Stereo Enhancement",
256 "Harman International VMAx",
257 "Nvidea 3D Stereo Enhancement",
258 "Philips Incredible Sound",
259 "Texas Instruments 3D Stereo Enhancement",
260 "VLSI Technology 3D Stereo Enhancement",
261 "TriTech 3D Stereo Enhancement",
262 "Realtek 3D Stereo Enhancement",
263 "Samsung 3D Stereo Enhancement",
264 "Wolfson Microelectronics 3D Enhancement",
265 "Delta Integration 3D Enhancement",
266 "SigmaTel 3D Enhancement",
267 "Reserved 27",
268 "Rockwell 3D Stereo Enhancement",
269 "Reserved 29",
270 "Reserved 30",
271 "Reserved 31"
272 };
273
274 static char *ac97feature[] = {
275 "mic channel",
276 "reserved",
277 "tone",
278 "simulated stereo",
279 "headphone",
280 "bass boost",
281 "18 bit DAC",
282 "20 bit DAC",
283 "18 bit ADC",
284 "20 bit ADC"
285 };
286
287 static char *ac97extfeature[] = {
288 "variable rate PCM",
289 "double rate PCM",
290 "reserved 1",
291 "variable rate mic",
292 "reserved 2",
293 "reserved 3",
294 "center DAC",
295 "surround DAC",
296 "LFE DAC",
297 "AMAP",
298 "reserved 4",
299 "reserved 5",
300 "reserved 6",
301 "reserved 7",
302 };
303
304 u_int16_t
305 ac97_rdcd(struct ac97_info *codec, int reg)
306 {
307 if (codec->flags & AC97_F_RDCD_BUG) {
308 u_int16_t i[2], j = 100;
309
310 i[0] = AC97_READ(codec->methods, codec->devinfo, reg);
311 i[1] = AC97_READ(codec->methods, codec->devinfo, reg);
312 while (i[0] != i[1] && j)
313 i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg);
314 #if 0
315 if (j < 100) {
316 device_printf(codec->dev, "%s(): Inconsistent register value at"
317 " 0x%08x (retry: %d)\n", __func__, reg, 100 - j);
318 }
319 #endif
320 return i[!(j & 1)];
321 }
322 return AC97_READ(codec->methods, codec->devinfo, reg);
323 }
324
325 void
326 ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val)
327 {
328 AC97_WRITE(codec->methods, codec->devinfo, reg, val);
329 }
330
331 static void
332 ac97_reset(struct ac97_info *codec)
333 {
334 u_int32_t i, ps;
335 ac97_wrcd(codec, AC97_REG_RESET, 0);
336 for (i = 0; i < 500; i++) {
337 ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS;
338 if (ps == AC97_POWER_STATUS)
339 return;
340 DELAY(1000);
341 }
342 device_printf(codec->dev, "AC97 reset timed out.\n");
343 }
344
345 int
346 ac97_setrate(struct ac97_info *codec, int which, int rate)
347 {
348 u_int16_t v;
349
350 switch(which) {
351 case AC97_REGEXT_FDACRATE:
352 case AC97_REGEXT_SDACRATE:
353 case AC97_REGEXT_LDACRATE:
354 case AC97_REGEXT_LADCRATE:
355 case AC97_REGEXT_MADCRATE:
356 break;
357
358 default:
359 return -1;
360 }
361
362 snd_mtxlock(codec->lock);
363 if (rate != 0) {
364 v = rate;
365 if (codec->extstat & AC97_EXTCAP_DRA)
366 v >>= 1;
367 ac97_wrcd(codec, which, v);
368 }
369 v = ac97_rdcd(codec, which);
370 if (codec->extstat & AC97_EXTCAP_DRA)
371 v <<= 1;
372 snd_mtxunlock(codec->lock);
373 return v;
374 }
375
376 int
377 ac97_setextmode(struct ac97_info *codec, u_int16_t mode)
378 {
379 mode &= AC97_EXTCAPS;
380 if ((mode & ~codec->extcaps) != 0) {
381 device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n",
382 mode);
383 return -1;
384 }
385 snd_mtxlock(codec->lock);
386 ac97_wrcd(codec, AC97_REGEXT_STAT, mode);
387 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
388 snd_mtxunlock(codec->lock);
389 return (mode == codec->extstat)? 0 : -1;
390 }
391
392 u_int16_t
393 ac97_getextmode(struct ac97_info *codec)
394 {
395 return codec->extstat;
396 }
397
398 u_int16_t
399 ac97_getextcaps(struct ac97_info *codec)
400 {
401 return codec->extcaps;
402 }
403
404 u_int16_t
405 ac97_getcaps(struct ac97_info *codec)
406 {
407 return codec->caps;
408 }
409
410 u_int32_t
411 ac97_getsubvendor(struct ac97_info *codec)
412 {
413 return codec->subvendor;
414 }
415
416 static int
417 ac97_setrecsrc(struct ac97_info *codec, int channel)
418 {
419 struct ac97mixtable_entry *e = &codec->mix[channel];
420
421 if (e->recidx > 0) {
422 int val = e->recidx - 1;
423 val |= val << 8;
424 snd_mtxlock(codec->lock);
425 ac97_wrcd(codec, AC97_REG_RECSEL, val);
426 snd_mtxunlock(codec->lock);
427 return 0;
428 } else
429 return -1;
430 }
431
432 static int
433 ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
434 {
435 struct ac97mixtable_entry *e = &codec->mix[channel];
436
437 if (e->reg && e->enable && e->bits) {
438 int mask, max, val, reg;
439
440 reg = (e->reg >= 0) ? e->reg : -e->reg; /* AC97 register */
441 max = (1 << e->bits) - 1; /* actual range */
442 mask = (max << 8) | max; /* bits of interest */
443
444 if (!e->stereo)
445 right = left;
446
447 /*
448 * Invert the range if the polarity requires so,
449 * then scale to 0..max-1 to compute the value to
450 * write into the codec, and scale back to 0..100
451 * for the return value.
452 */
453 if (e->reg > 0) {
454 left = 100 - left;
455 right = 100 - right;
456 }
457
458 left = (left * max) / 100;
459 right = (right * max) / 100;
460
461 val = (left << 8) | right;
462
463 left = (left * 100) / max;
464 right = (right * 100) / max;
465
466 if (e->reg > 0) {
467 left = 100 - left;
468 right = 100 - right;
469 }
470
471 /*
472 * For mono controls, trim val and mask, also taking
473 * care of e->ofs (offset of control field).
474 */
475 if (e->ofs) {
476 val &= max;
477 val <<= e->ofs;
478 mask = (max << e->ofs);
479 }
480
481 /*
482 * If we have a mute bit, add it to the mask and
483 * update val and set mute if both channels require a
484 * zero volume.
485 */
486 if (e->mute == 1) {
487 mask |= AC97_MUTE;
488 if (left == 0 && right == 0)
489 val = AC97_MUTE;
490 }
491
492 /*
493 * If the mask bit is set, do not alter the other bits.
494 */
495 snd_mtxlock(codec->lock);
496 if (e->mask) {
497 int cur = ac97_rdcd(codec, reg);
498 val |= cur & ~(mask);
499 }
500 ac97_wrcd(codec, reg, val);
501 snd_mtxunlock(codec->lock);
502 return left | (right << 8);
503 } else {
504 #if 0
505 printf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable);
506 #endif
507 return -1;
508 }
509 }
510
511 static void
512 ac97_fix_auxout(struct ac97_info *codec)
513 {
514 int keep_ogain;
515
516 /*
517 * By default, The ac97 aux_out register (0x04) corresponds to OSS's
518 * OGAIN setting.
519 *
520 * We first check whether aux_out is a valid register. If not
521 * we may not want to keep ogain.
522 */
523 keep_ogain = ac97_rdcd(codec, AC97_MIX_AUXOUT) & 0x8000;
524
525 /*
526 * Determine what AUX_OUT really means, it can be:
527 *
528 * 1. Headphone out.
529 * 2. 4-Channel Out
530 * 3. True line level out (effectively master volume).
531 *
532 * See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}.
533 */
534 if (codec->extcaps & AC97_EXTCAP_SDAC &&
535 ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) {
536 codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND;
537 keep_ogain = 1;
538 }
539
540 if (keep_ogain == 0) {
541 bzero(&codec->mix[SOUND_MIXER_OGAIN],
542 sizeof(codec->mix[SOUND_MIXER_OGAIN]));
543 }
544 }
545
546 static void
547 ac97_fix_tone(struct ac97_info *codec)
548 {
549 /*
550 * YMF chips does not indicate tone and 3D enhancement capability
551 * in the AC97_REG_RESET register.
552 */
553 switch (codec->id) {
554 case 0x594d4800: /* YMF743 */
555 case 0x594d4803: /* YMF753 */
556 codec->caps |= AC97_CAP_TONE;
557 codec->se |= 0x04;
558 break;
559 case 0x594d4802: /* YMF752 */
560 codec->se |= 0x04;
561 break;
562 default:
563 break;
564 }
565
566 /* Hide treble and bass if they don't exist */
567 if ((codec->caps & AC97_CAP_TONE) == 0) {
568 bzero(&codec->mix[SOUND_MIXER_BASS],
569 sizeof(codec->mix[SOUND_MIXER_BASS]));
570 bzero(&codec->mix[SOUND_MIXER_TREBLE],
571 sizeof(codec->mix[SOUND_MIXER_TREBLE]));
572 }
573 }
574
575 static const char*
576 ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
577 {
578 if (cname == NULL) {
579 sprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
580 return buf;
581 }
582
583 if (vname == NULL) vname = "Unknown";
584
585 if (bootverbose) {
586 sprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
587 } else {
588 sprintf(buf, "%s %s AC97 Codec", vname, cname);
589 }
590 return buf;
591 }
592
593 static unsigned
594 ac97_initmixer(struct ac97_info *codec)
595 {
596 ac97_patch codec_patch;
597 const char *cname, *vname;
598 char desc[80];
599 u_int8_t model, step;
600 unsigned i, j, k, bit, old;
601 u_int32_t id;
602 int reg;
603
604 snd_mtxlock(codec->lock);
605 codec->count = AC97_INIT(codec->methods, codec->devinfo);
606 if (codec->count == 0) {
607 device_printf(codec->dev, "ac97 codec init failed\n");
608 snd_mtxunlock(codec->lock);
609 return ENODEV;
610 }
611
612 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
613 ac97_reset(codec);
614 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
615
616 i = ac97_rdcd(codec, AC97_REG_RESET);
617 j = ac97_rdcd(codec, AC97_REG_RESET);
618 k = ac97_rdcd(codec, AC97_REG_RESET);
619 /*
620 * Let see if this codec can return consistent value.
621 * If not, turn on aggressive read workaround
622 * (STAC9704 comes in mind).
623 */
624 if (i != j || j != k) {
625 codec->flags |= AC97_F_RDCD_BUG;
626 i = ac97_rdcd(codec, AC97_REG_RESET);
627 }
628 codec->caps = i & 0x03ff;
629 codec->se = (i & 0x7c00) >> 10;
630
631 id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2);
632 if (id == 0 || id == 0xffffffff) {
633 device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id);
634 snd_mtxunlock(codec->lock);
635 return ENODEV;
636 }
637
638 codec->id = id;
639 codec->subvendor = (u_int32_t)pci_get_subdevice(codec->dev) << 16;
640 codec->subvendor |= (u_int32_t)pci_get_subvendor(codec->dev) &
641 0x0000ffff;
642 codec->noext = 0;
643 codec_patch = NULL;
644
645 cname = NULL;
646 model = step = 0;
647 for (i = 0; ac97codecid[i].id; i++) {
648 u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask;
649 if ((ac97codecid[i].id & modelmask) == (id & modelmask)) {
650 codec->noext = ac97codecid[i].noext;
651 codec_patch = ac97codecid[i].patch;
652 cname = ac97codecid[i].name;
653 model = (id & modelmask) & 0xff;
654 step = (id & ~modelmask) & 0xff;
655 break;
656 }
657 }
658
659 vname = NULL;
660 for (i = 0; ac97vendorid[i].id; i++) {
661 if (ac97vendorid[i].id == (id & 0xffffff00)) {
662 vname = ac97vendorid[i].name;
663 break;
664 }
665 }
666
667 codec->extcaps = 0;
668 codec->extid = 0;
669 codec->extstat = 0;
670 if (!codec->noext) {
671 i = ac97_rdcd(codec, AC97_REGEXT_ID);
672 if (i != 0xffff) {
673 codec->extcaps = i & 0x3fff;
674 codec->extid = (i & 0xc000) >> 14;
675 codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
676 }
677 }
678
679 for (i = 0; i < AC97_MIXER_SIZE; i++) {
680 codec->mix[i] = ac97mixtable_default[i];
681 }
682 ac97_fix_auxout(codec);
683 ac97_fix_tone(codec);
684 if (codec_patch)
685 codec_patch(codec);
686
687 for (i = 0; i < AC97_MIXER_SIZE; i++) {
688 k = codec->noext? codec->mix[i].enable : 1;
689 reg = codec->mix[i].reg;
690 if (reg < 0)
691 reg = -reg;
692 if (k && reg) {
693 j = old = ac97_rdcd(codec, reg);
694 /*
695 * Test for mute bit (except for AC97_MIX_TONE,
696 * where we simply assume it as available).
697 */
698 if (codec->mix[i].mute) {
699 ac97_wrcd(codec, reg, j | 0x8000);
700 j = ac97_rdcd(codec, reg);
701 } else
702 j |= 0x8000;
703 if ((j & 0x8000)) {
704 /*
705 * Test whether the control width should be
706 * 4, 5 or 6 bit. For 5bit register, we should
707 * test it whether it's really 5 or 6bit. Leave
708 * 4bit register alone, because sometimes an
709 * attempt to write past 4th bit may cause
710 * incorrect result especially for AC97_MIX_BEEP
711 * (ac97 2.3).
712 */
713 bit = codec->mix[i].bits;
714 if (bit == 5)
715 bit++;
716 j = ((1 << bit) - 1) << codec->mix[i].ofs;
717 ac97_wrcd(codec, reg,
718 j | (codec->mix[i].mute ? 0x8000 : 0));
719 k = ac97_rdcd(codec, reg) & j;
720 k >>= codec->mix[i].ofs;
721 if (reg == AC97_MIX_TONE &&
722 ((k & 0x0001) == 0x0000))
723 k >>= 1;
724 for (j = 0; k >> j; j++)
725 ;
726 if (j != 0) {
727 #if 0
728 device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n",
729 i, k, bit, codec->mix[i].bits, j);
730 #endif
731 codec->mix[i].enable = 1;
732 codec->mix[i].bits = j;
733 } else if (reg == AC97_MIX_BEEP) {
734 /*
735 * Few codec such as CX20468-21 does
736 * have this control register, although
737 * the only usable part is the mute bit.
738 */
739 codec->mix[i].enable = 1;
740 } else
741 codec->mix[i].enable = 0;
742 } else
743 codec->mix[i].enable = 0;
744 ac97_wrcd(codec, reg, old);
745 }
746 #if 0
747 printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits);
748 #endif
749 }
750
751 device_printf(codec->dev, "<%s>\n",
752 ac97_hw_desc(codec->id, vname, cname, desc));
753
754 if (bootverbose) {
755 if (codec->flags & AC97_F_RDCD_BUG)
756 device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
757 device_printf(codec->dev, "Codec features ");
758 for (i = j = 0; i < 10; i++)
759 if (codec->caps & (1 << i))
760 printf("%s%s", j++? ", " : "", ac97feature[i]);
761 printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
762 printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]);
763
764 if (codec->extcaps != 0 || codec->extid) {
765 device_printf(codec->dev, "%s codec",
766 codec->extid? "Secondary" : "Primary");
767 if (codec->extcaps)
768 printf(" extended features ");
769 for (i = j = 0; i < 14; i++)
770 if (codec->extcaps & (1 << i))
771 printf("%s%s", j++? ", " : "", ac97extfeature[i]);
772 printf("\n");
773 }
774 }
775
776 i = 0;
777 while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
778 if (++i == 100) {
779 device_printf(codec->dev, "ac97 codec reports dac not ready\n");
780 break;
781 }
782 DELAY(1000);
783 }
784 if (bootverbose)
785 device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i);
786 snd_mtxunlock(codec->lock);
787 return 0;
788 }
789
790 static unsigned
791 ac97_reinitmixer(struct ac97_info *codec)
792 {
793 snd_mtxlock(codec->lock);
794 codec->count = AC97_INIT(codec->methods, codec->devinfo);
795 if (codec->count == 0) {
796 device_printf(codec->dev, "ac97 codec init failed\n");
797 snd_mtxunlock(codec->lock);
798 return ENODEV;
799 }
800
801 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
802 ac97_reset(codec);
803 ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
804
805 if (!codec->noext) {
806 ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat);
807 if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS)
808 != codec->extstat)
809 device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n",
810 codec->extstat,
811 ac97_rdcd(codec, AC97_REGEXT_STAT) &
812 AC97_EXTCAPS);
813 }
814
815 if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
816 device_printf(codec->dev, "ac97 codec reports dac not ready\n");
817 snd_mtxunlock(codec->lock);
818 return 0;
819 }
820
821 struct ac97_info *
822 ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
823 {
824 struct ac97_info *codec;
825 int eapdinv;
826
827 codec = malloc(sizeof(*codec), M_AC97, M_WAITOK | M_ZERO);
828 snprintf(codec->name, sizeof(codec->name), "%s:ac97",
829 device_get_nameunit(dev));
830 codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
831 codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO);
832 codec->dev = dev;
833 codec->devinfo = devinfo;
834 codec->flags = 0;
835 if (resource_int_value(device_get_name(dev), device_get_unit(dev),
836 "eapdinv", &eapdinv) == 0) {
837 if (eapdinv != 0)
838 codec->flags |= AC97_F_EAPD_INV;
839 }
840 return codec;
841 }
842
843 void
844 ac97_destroy(struct ac97_info *codec)
845 {
846 snd_mtxlock(codec->lock);
847 if (codec->methods != NULL)
848 kobj_delete(codec->methods, M_AC97);
849 snd_mtxfree(codec->lock);
850 free(codec, M_AC97);
851 }
852
853 void
854 ac97_setflags(struct ac97_info *codec, u_int32_t val)
855 {
856 codec->flags = val;
857 }
858
859 u_int32_t
860 ac97_getflags(struct ac97_info *codec)
861 {
862 return codec->flags;
863 }
864
865 /* -------------------------------------------------------------------- */
866
867 #ifdef SND_DYNSYSCTL
868 static int
869 sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)
870 {
871 struct ac97_info *codec;
872 int ea, inv, err = 0;
873 u_int16_t val;
874
875 codec = oidp->oid_arg1;
876 if (codec == NULL || codec->id == 0 || codec->lock == NULL)
877 return EINVAL;
878 snd_mtxlock(codec->lock);
879 val = ac97_rdcd(codec, AC97_REG_POWER);
880 inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1;
881 ea = (val >> 15) ^ inv;
882 snd_mtxunlock(codec->lock);
883 err = sysctl_handle_int(oidp, &ea, 0, req);
884 if (err == 0 && req->newptr != NULL) {
885 if (ea != 0 && ea != 1)
886 return EINVAL;
887 if (ea != ((val >> 15) ^ inv)) {
888 snd_mtxlock(codec->lock);
889 ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000);
890 snd_mtxunlock(codec->lock);
891 }
892 }
893 return err;
894 }
895 #endif
896
897 static void
898 ac97_init_sysctl(struct ac97_info *codec)
899 {
900 #ifdef SND_DYNSYSCTL
901 u_int16_t orig, val;
902
903 if (codec == NULL || codec->dev == NULL)
904 return;
905 snd_mtxlock(codec->lock);
906 orig = ac97_rdcd(codec, AC97_REG_POWER);
907 ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000);
908 val = ac97_rdcd(codec, AC97_REG_POWER);
909 ac97_wrcd(codec, AC97_REG_POWER, orig);
910 snd_mtxunlock(codec->lock);
911 if ((val & 0x8000) == (orig & 0x8000))
912 return;
913 SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev),
914 SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)),
915 OID_AUTO, "eapd", CTLTYPE_INT | CTLFLAG_RW,
916 codec, sizeof(codec), sysctl_hw_snd_ac97_eapd,
917 "I", "AC97 External Amplifier");
918 #endif
919 }
920
921 static int
922 ac97mix_init(struct snd_mixer *m)
923 {
924 struct ac97_info *codec = mix_getdevinfo(m);
925 u_int32_t i, mask;
926
927 if (codec == NULL)
928 return -1;
929
930 if (ac97_initmixer(codec))
931 return -1;
932
933 switch (codec->id) {
934 case 0x41445374: /* AD1981B */
935 switch (codec->subvendor) {
936 case 0x02d91014:
937 /*
938 * IBM Thinkcentre:
939 *
940 * Tie "ogain" and "phout" to "vol" since its
941 * master volume is basically useless and can't
942 * control anything.
943 */
944 mask = 0;
945 if (codec->mix[SOUND_MIXER_OGAIN].enable)
946 mask |= SOUND_MASK_OGAIN;
947 if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
948 mask |= SOUND_MASK_PHONEOUT;
949 if (codec->mix[SOUND_MIXER_VOLUME].enable)
950 mix_setparentchild(m, SOUND_MIXER_VOLUME,
951 mask);
952 else {
953 mix_setparentchild(m, SOUND_MIXER_VOLUME,
954 mask);
955 mix_setrealdev(m, SOUND_MIXER_VOLUME,
956 SOUND_MIXER_NONE);
957 }
958 break;
959 case 0x099c103c:
960 /*
961 * HP nx6110:
962 *
963 * By default, "vol" is controlling internal speakers
964 * (not a master volume!) and "ogain" is controlling
965 * headphone. Enable dummy "phout" so it can be
966 * remapped to internal speakers and virtualize
967 * "vol" to control both.
968 */
969 codec->mix[SOUND_MIXER_OGAIN].enable = 1;
970 codec->mix[SOUND_MIXER_PHONEOUT].enable = 1;
971 mix_setrealdev(m, SOUND_MIXER_PHONEOUT,
972 SOUND_MIXER_VOLUME);
973 mix_setrealdev(m, SOUND_MIXER_VOLUME,
974 SOUND_MIXER_NONE);
975 mix_setparentchild(m, SOUND_MIXER_VOLUME,
976 SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT);
977 break;
978 default:
979 break;
980 }
981 break;
982 case 0x434d4941: /* CMI9738 */
983 case 0x434d4961: /* CMI9739 */
984 case 0x434d4978: /* CMI9761 */
985 case 0x434d4982: /* CMI9761 */
986 case 0x434d4983: /* CMI9761 */
987 ac97_wrcd(codec, AC97_MIX_PCM, 0);
988 bzero(&codec->mix[SOUND_MIXER_PCM],
989 sizeof(codec->mix[SOUND_MIXER_PCM]));
990 pcm_setflags(codec->dev, pcm_getflags(codec->dev) |
991 SD_F_SOFTPCMVOL);
992 /* XXX How about master volume ? */
993 break;
994 default:
995 break;
996 }
997
998 #if 0
999 /* XXX For the sake of debugging purposes */
1000 mix_setparentchild(m, SOUND_MIXER_VOLUME,
1001 SOUND_MASK_PCM | SOUND_MASK_CD);
1002 mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
1003 ac97_wrcd(codec, AC97_MIX_MASTER, 0);
1004 #endif
1005
1006 mask = 0;
1007 for (i = 0; i < AC97_MIXER_SIZE; i++)
1008 mask |= codec->mix[i].enable? 1 << i : 0;
1009 mix_setdevs(m, mask);
1010
1011 mask = 0;
1012 for (i = 0; i < AC97_MIXER_SIZE; i++)
1013 mask |= codec->mix[i].recidx? 1 << i : 0;
1014 mix_setrecdevs(m, mask);
1015
1016 ac97_init_sysctl(codec);
1017
1018 return 0;
1019 }
1020
1021 static int
1022 ac97mix_uninit(struct snd_mixer *m)
1023 {
1024 struct ac97_info *codec = mix_getdevinfo(m);
1025
1026 if (codec == NULL)
1027 return -1;
1028 /*
1029 if (ac97_uninitmixer(codec))
1030 return -1;
1031 */
1032 ac97_destroy(codec);
1033 return 0;
1034 }
1035
1036 static int
1037 ac97mix_reinit(struct snd_mixer *m)
1038 {
1039 struct ac97_info *codec = mix_getdevinfo(m);
1040
1041 if (codec == NULL)
1042 return -1;
1043 return ac97_reinitmixer(codec);
1044 }
1045
1046 static int
1047 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1048 {
1049 struct ac97_info *codec = mix_getdevinfo(m);
1050
1051 if (codec == NULL || dev >= AC97_MIXER_SIZE)
1052 return -1;
1053 return ac97_setmixer(codec, dev, left, right);
1054 }
1055
1056 static int
1057 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1058 {
1059 int i;
1060 struct ac97_info *codec = mix_getdevinfo(m);
1061
1062 if (codec == NULL)
1063 return -1;
1064 for (i = 0; i < AC97_MIXER_SIZE; i++)
1065 if ((src & (1 << i)) != 0)
1066 break;
1067 return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
1068 }
1069
1070 static kobj_method_t ac97mixer_methods[] = {
1071 KOBJMETHOD(mixer_init, ac97mix_init),
1072 KOBJMETHOD(mixer_uninit, ac97mix_uninit),
1073 KOBJMETHOD(mixer_reinit, ac97mix_reinit),
1074 KOBJMETHOD(mixer_set, ac97mix_set),
1075 KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc),
1076 { 0, 0 }
1077 };
1078 MIXER_DECLARE(ac97mixer);
1079
1080 /* -------------------------------------------------------------------- */
1081
1082 kobj_class_t
1083 ac97_getmixerclass(void)
1084 {
1085 return &ac97mixer_class;
1086 }
Cache object: 8482716d449e56fd87b4b78e5a8c5fd6
|