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