xref: /freebsd/sys/dev/sound/pcm/ac97.c (revision faf25f48d601ae39f5752602f3020e2e92605625)
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 	device_t pdev;
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 	pdev = codec->dev;
645 	while (strcmp(device_get_name(device_get_parent(pdev)), "pci") != 0) {
646 		/* find the top-level PCI device handler */
647 		pdev = device_get_parent(pdev);
648 	}
649 	codec->id = id;
650 	codec->subvendor = (u_int32_t)pci_get_subdevice(pdev) << 16;
651 	codec->subvendor |= (u_int32_t)pci_get_subvendor(pdev) &
652 	    0x0000ffff;
653 	codec->noext = 0;
654 	codec_patch = NULL;
655 
656 	cname = NULL;
657 	for (i = 0; ac97codecid[i].id; i++) {
658 		u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask;
659 		if ((ac97codecid[i].id & modelmask) == (id & modelmask)) {
660 			codec->noext = ac97codecid[i].noext;
661 			codec_patch = ac97codecid[i].patch;
662 			cname = ac97codecid[i].name;
663 			break;
664 		}
665 	}
666 
667 	vname = NULL;
668 	for (i = 0; ac97vendorid[i].id; i++) {
669 		if (ac97vendorid[i].id == (id & 0xffffff00)) {
670 			vname = ac97vendorid[i].name;
671 			break;
672 		}
673 	}
674 
675 	codec->extcaps = 0;
676 	codec->extid = 0;
677 	codec->extstat = 0;
678 	if (!codec->noext) {
679 		i = ac97_rdcd(codec, AC97_REGEXT_ID);
680 		if (i != 0xffff) {
681 			codec->extcaps = i & 0x3fff;
682 			codec->extid =  (i & 0xc000) >> 14;
683 			codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
684 		}
685 	}
686 
687 	for (i = 0; i < AC97_MIXER_SIZE; i++) {
688 		codec->mix[i] = ac97mixtable_default[i];
689 	}
690 	ac97_fix_auxout(codec);
691 	ac97_fix_tone(codec);
692 	if (codec_patch)
693 		codec_patch(codec);
694 
695 	for (i = 0; i < AC97_MIXER_SIZE; i++) {
696 		k = codec->noext? codec->mix[i].enable : 1;
697 		reg = codec->mix[i].reg;
698 		if (reg < 0)
699 			reg = -reg;
700 		if (k && reg) {
701 			j = old = ac97_rdcd(codec, reg);
702 			/*
703 			 * Test for mute bit (except for AC97_MIX_TONE,
704 			 * where we simply assume it as available).
705 			 */
706 			if (codec->mix[i].mute) {
707 				ac97_wrcd(codec, reg, j | 0x8000);
708 				j = ac97_rdcd(codec, reg);
709 			} else
710 				j |= 0x8000;
711 			if ((j & 0x8000)) {
712 				/*
713 				 * Test whether the control width should be
714 				 * 4, 5 or 6 bit. For 5bit register, we should
715 				 * test it whether it's really 5 or 6bit. Leave
716 				 * 4bit register alone, because sometimes an
717 				 * attempt to write past 4th bit may cause
718 				 * incorrect result especially for AC97_MIX_BEEP
719 				 * (ac97 2.3).
720 				 */
721 				bit = codec->mix[i].bits;
722 				if (bit == 5)
723 					bit++;
724 				j = ((1 << bit) - 1) << codec->mix[i].ofs;
725 				ac97_wrcd(codec, reg,
726 					j | (codec->mix[i].mute ? 0x8000 : 0));
727 				k = ac97_rdcd(codec, reg) & j;
728 				k >>= codec->mix[i].ofs;
729 				if (reg == AC97_MIX_TONE &&
730 							((k & 0x0001) == 0x0000))
731 					k >>= 1;
732 				for (j = 0; k >> j; j++)
733 					;
734 				if (j != 0) {
735 #if 0
736 					device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n",
737 						i, k, bit, codec->mix[i].bits, j);
738 #endif
739 					codec->mix[i].enable = 1;
740 					codec->mix[i].bits = j;
741 				} else if (reg == AC97_MIX_BEEP) {
742 					/*
743 					 * Few codec such as CX20468-21 does
744 					 * have this control register, although
745 					 * the only usable part is the mute bit.
746 					 */
747 					codec->mix[i].enable = 1;
748 				} else
749 					codec->mix[i].enable = 0;
750 			} else
751 				codec->mix[i].enable = 0;
752 			ac97_wrcd(codec, reg, old);
753 		}
754 #if 0
755 		printf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits);
756 #endif
757 	}
758 
759 	device_printf(codec->dev, "<%s>\n",
760 		      ac97_hw_desc(codec->id, vname, cname, desc));
761 
762 	if (bootverbose) {
763 		if (codec->flags & AC97_F_RDCD_BUG)
764 			device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
765 		device_printf(codec->dev, "Codec features ");
766 		for (i = j = 0; i < 10; i++)
767 			if (codec->caps & (1 << i))
768 				printf("%s%s", j++? ", " : "", ac97feature[i]);
769 		printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
770 		printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]);
771 
772 		if (codec->extcaps != 0 || codec->extid) {
773 			device_printf(codec->dev, "%s codec",
774 				      codec->extid? "Secondary" : "Primary");
775 			if (codec->extcaps)
776 				printf(" extended features ");
777 			for (i = j = 0; i < 14; i++)
778 				if (codec->extcaps & (1 << i))
779 					printf("%s%s", j++? ", " : "", ac97extfeature[i]);
780 			printf("\n");
781 		}
782 	}
783 
784 	i = 0;
785 	while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
786 		if (++i == 100) {
787 			device_printf(codec->dev, "ac97 codec reports dac not ready\n");
788 			break;
789 		}
790 		DELAY(1000);
791 	}
792 	if (bootverbose)
793 		device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i);
794 	snd_mtxunlock(codec->lock);
795 	return 0;
796 }
797 
798 static unsigned
799 ac97_reinitmixer(struct ac97_info *codec)
800 {
801 	snd_mtxlock(codec->lock);
802 	codec->count = AC97_INIT(codec->methods, codec->devinfo);
803 	if (codec->count == 0) {
804 		device_printf(codec->dev, "ac97 codec init failed\n");
805 		snd_mtxunlock(codec->lock);
806 		return ENODEV;
807 	}
808 
809 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
810 	ac97_reset(codec);
811 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
812 
813 	if (!codec->noext) {
814 		ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat);
815 		if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS)
816 		    != codec->extstat)
817 			device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n",
818 				      codec->extstat,
819 				      ac97_rdcd(codec, AC97_REGEXT_STAT) &
820 				      AC97_EXTCAPS);
821 	}
822 
823 	if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
824 		device_printf(codec->dev, "ac97 codec reports dac not ready\n");
825 	snd_mtxunlock(codec->lock);
826 	return 0;
827 }
828 
829 struct ac97_info *
830 ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
831 {
832 	struct ac97_info *codec;
833 	int i;
834 
835 	codec = malloc(sizeof(*codec), M_AC97, M_WAITOK | M_ZERO);
836 	snprintf(codec->name, sizeof(codec->name), "%s:ac97",
837 	    device_get_nameunit(dev));
838 	codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
839 	codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO);
840 	codec->dev = dev;
841 	codec->devinfo = devinfo;
842 	codec->flags = 0;
843 
844 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
845 	    "eapdinv", &i) == 0 && i != 0)
846 		codec->flags |= AC97_F_EAPD_INV;
847 
848 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
849 	    "softpcmvol", &i) == 0 && i != 0)
850 		pcm_setflags(dev, pcm_getflags(dev) | SD_F_SOFTPCMVOL);
851 
852 	return codec;
853 }
854 
855 void
856 ac97_destroy(struct ac97_info *codec)
857 {
858 	snd_mtxlock(codec->lock);
859 	if (codec->methods != NULL)
860 		kobj_delete(codec->methods, M_AC97);
861 	snd_mtxfree(codec->lock);
862 	free(codec, M_AC97);
863 }
864 
865 void
866 ac97_setflags(struct ac97_info *codec, u_int32_t val)
867 {
868 	codec->flags = val;
869 }
870 
871 u_int32_t
872 ac97_getflags(struct ac97_info *codec)
873 {
874 	return codec->flags;
875 }
876 
877 /* -------------------------------------------------------------------- */
878 
879 static int
880 sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)
881 {
882 	struct ac97_info *codec;
883 	int ea, inv, err = 0;
884 	u_int16_t val;
885 
886 	codec = oidp->oid_arg1;
887 	if (codec == NULL || codec->id == 0 || codec->lock == NULL)
888 		return EINVAL;
889 	snd_mtxlock(codec->lock);
890 	val = ac97_rdcd(codec, AC97_REG_POWER);
891 	inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1;
892 	ea = (val >> 15) ^ inv;
893 	snd_mtxunlock(codec->lock);
894 	err = sysctl_handle_int(oidp, &ea, 0, req);
895 	if (err == 0 && req->newptr != NULL) {
896 		if (ea != 0 && ea != 1)
897 			return EINVAL;
898 		if (ea != ((val >> 15) ^ inv)) {
899 			snd_mtxlock(codec->lock);
900 			ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000);
901 			snd_mtxunlock(codec->lock);
902 		}
903 	}
904 	return err;
905 }
906 
907 static void
908 ac97_init_sysctl(struct ac97_info *codec)
909 {
910 	u_int16_t orig, val;
911 
912 	if (codec == NULL || codec->dev == NULL)
913 		return;
914 	snd_mtxlock(codec->lock);
915 	orig = ac97_rdcd(codec, AC97_REG_POWER);
916 	ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000);
917 	val = ac97_rdcd(codec, AC97_REG_POWER);
918 	ac97_wrcd(codec, AC97_REG_POWER, orig);
919 	snd_mtxunlock(codec->lock);
920 	if ((val & 0x8000) == (orig & 0x8000))
921 		return;
922 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev),
923 	    SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)),
924             OID_AUTO, "eapd",
925 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
926 	    codec, sizeof(codec), sysctl_hw_snd_ac97_eapd,
927 	    "I", "AC97 External Amplifier");
928 }
929 
930 static int
931 ac97mix_init(struct snd_mixer *m)
932 {
933 	struct ac97_info *codec = mix_getdevinfo(m);
934 	u_int32_t i, mask;
935 
936 	if (codec == NULL)
937 		return -1;
938 
939 	if (ac97_initmixer(codec))
940 		return -1;
941 
942 	switch (codec->id) {
943 	case 0x41445374:	/* AD1981B */
944 		switch (codec->subvendor) {
945 		case 0x02d91014:
946 			/*
947 			 * IBM Thinkcentre:
948 			 *
949 			 * Tie "ogain" and "phout" to "vol" since its
950 			 * master volume is basically useless and can't
951 			 * control anything.
952 			 */
953 			mask = 0;
954 			if (codec->mix[SOUND_MIXER_OGAIN].enable)
955 				mask |= SOUND_MASK_OGAIN;
956 			if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
957 				mask |= SOUND_MASK_PHONEOUT;
958 			if (codec->mix[SOUND_MIXER_VOLUME].enable)
959 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
960 				    mask);
961 			else {
962 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
963 				    mask);
964 				mix_setrealdev(m, SOUND_MIXER_VOLUME,
965 				    SOUND_MIXER_NONE);
966 			}
967 			break;
968 		case 0x099c103c:
969 			/*
970 			 * HP nx6110:
971 			 *
972 			 * By default, "vol" is controlling internal speakers
973 			 * (not a master volume!) and "ogain" is controlling
974 			 * headphone. Enable dummy "phout" so it can be
975 			 * remapped to internal speakers and virtualize
976 			 * "vol" to control both.
977 			 */
978 			codec->mix[SOUND_MIXER_OGAIN].enable = 1;
979 			codec->mix[SOUND_MIXER_PHONEOUT].enable = 1;
980 			mix_setrealdev(m, SOUND_MIXER_PHONEOUT,
981 			    SOUND_MIXER_VOLUME);
982 			mix_setrealdev(m, SOUND_MIXER_VOLUME,
983 			    SOUND_MIXER_NONE);
984 			mix_setparentchild(m, SOUND_MIXER_VOLUME,
985 			    SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT);
986 			break;
987 		default:
988 			break;
989 		}
990 		break;
991 	case 0x434d4941:	/* CMI9738 */
992 	case 0x434d4961:	/* CMI9739 */
993 	case 0x434d4978:	/* CMI9761 */
994 	case 0x434d4982:	/* CMI9761 */
995 	case 0x434d4983:	/* CMI9761 */
996 		bzero(&codec->mix[SOUND_MIXER_PCM],
997 		    sizeof(codec->mix[SOUND_MIXER_PCM]));
998 		pcm_setflags(codec->dev, pcm_getflags(codec->dev) |
999 		    SD_F_SOFTPCMVOL);
1000 		/* XXX How about master volume ? */
1001 		break;
1002 	default:
1003 		break;
1004 	}
1005 
1006 	if (pcm_getflags(codec->dev) & SD_F_SOFTPCMVOL)
1007 		ac97_wrcd(codec, AC97_MIX_PCM, 0);
1008 #if 0
1009 	/* XXX For the sake of debugging purposes */
1010 	mix_setparentchild(m, SOUND_MIXER_VOLUME,
1011 	    SOUND_MASK_PCM | SOUND_MASK_CD);
1012 	mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
1013 	ac97_wrcd(codec, AC97_MIX_MASTER, 0);
1014 #endif
1015 
1016 	mask = 0;
1017 	for (i = 0; i < AC97_MIXER_SIZE; i++)
1018 		mask |= codec->mix[i].enable? 1 << i : 0;
1019 	mix_setdevs(m, mask);
1020 
1021 	mask = 0;
1022 	for (i = 0; i < AC97_MIXER_SIZE; i++)
1023 		mask |= codec->mix[i].recidx? 1 << i : 0;
1024 	mix_setrecdevs(m, mask);
1025 
1026 	ac97_init_sysctl(codec);
1027 
1028 	return 0;
1029 }
1030 
1031 static int
1032 ac97mix_uninit(struct snd_mixer *m)
1033 {
1034 	struct ac97_info *codec = mix_getdevinfo(m);
1035 
1036 	if (codec == NULL)
1037 		return -1;
1038 	/*
1039 	if (ac97_uninitmixer(codec))
1040 		return -1;
1041 	*/
1042 	ac97_destroy(codec);
1043 	return 0;
1044 }
1045 
1046 static int
1047 ac97mix_reinit(struct snd_mixer *m)
1048 {
1049 	struct ac97_info *codec = mix_getdevinfo(m);
1050 
1051 	if (codec == NULL)
1052 		return -1;
1053 	return ac97_reinitmixer(codec);
1054 }
1055 
1056 static int
1057 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1058 {
1059 	struct ac97_info *codec = mix_getdevinfo(m);
1060 
1061 	if (codec == NULL || dev >= AC97_MIXER_SIZE)
1062 		return -1;
1063 	return ac97_setmixer(codec, dev, left, right);
1064 }
1065 
1066 static u_int32_t
1067 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1068 {
1069 	int i;
1070 	struct ac97_info *codec = mix_getdevinfo(m);
1071 
1072 	if (codec == NULL)
1073 		return -1;
1074 	for (i = 0; i < AC97_MIXER_SIZE; i++)
1075 		if ((src & (1 << i)) != 0)
1076 			break;
1077 	return (ac97_setrecsrc(codec, i) == 0)? 1U << i : 0xffffffffU;
1078 }
1079 
1080 static kobj_method_t ac97mixer_methods[] = {
1081     	KOBJMETHOD(mixer_init,		ac97mix_init),
1082     	KOBJMETHOD(mixer_uninit,	ac97mix_uninit),
1083     	KOBJMETHOD(mixer_reinit,	ac97mix_reinit),
1084     	KOBJMETHOD(mixer_set,		ac97mix_set),
1085     	KOBJMETHOD(mixer_setrecsrc,	ac97mix_setrecsrc),
1086 	KOBJMETHOD_END
1087 };
1088 MIXER_DECLARE(ac97mixer);
1089 
1090 /* -------------------------------------------------------------------- */
1091 
1092 kobj_class_t
1093 ac97_getmixerclass(void)
1094 {
1095 	return &ac97mixer_class;
1096 }
1097