xref: /dragonfly/sys/dev/sound/pcm/ac97.c (revision 8accc937)
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  * $FreeBSD: src/sys/dev/sound/pcm/ac97.c,v 1.53.2.6 2007/10/31 04:00:07 ariff Exp $
27  */
28 
29 #include <dev/sound/pcm/sound.h>
30 #include <dev/sound/pcm/ac97.h>
31 #include <dev/sound/pcm/ac97_patch.h>
32 
33 #include <bus/pci/pcivar.h>
34 
35 #include "mixer_if.h"
36 
37 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/ac97.c,v 1.26 2007/11/30 07:59:56 hasso Exp $");
38 
39 MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
40 
41 struct ac97mixtable_entry {
42 	int	 reg:8;		/* register index		*/
43 				/* reg < 0 if inverted polarity	*/
44 	unsigned bits:4;	/* width of control field	*/
45 	unsigned ofs:4;		/* offset (only if stereo=0)	*/
46 	unsigned stereo:1;	/* set for stereo controls	*/
47 	unsigned mute:1;	/* bit15 is MUTE		*/
48 	unsigned recidx:4;	/* index in rec mux		*/
49 	unsigned mask:1;	/* use only masked bits		*/
50 	unsigned enable:1;	/* entry is enabled		*/
51 };
52 
53 #define AC97_NAMELEN	16
54 struct ac97_info {
55 	kobj_t methods;
56 	device_t dev;
57 	void *devinfo;
58 	u_int32_t id;
59 	u_int32_t subvendor;
60 	unsigned count, caps, se, extcaps, extid, extstat, noext:1;
61 	u_int32_t flags;
62 	struct ac97mixtable_entry mix[32];
63 	char name[AC97_NAMELEN];
64 	sndlock_t	lock;
65 };
66 
67 struct ac97_vendorid {
68 	u_int32_t   id;
69 	const char *name;
70 };
71 
72 struct ac97_codecid {
73 	u_int32_t  id;
74 	u_int8_t   stepmask;
75 	u_int8_t   noext:1;
76 	char 	  *name;
77 	ac97_patch patch;
78 };
79 
80 static const struct ac97mixtable_entry ac97mixtable_default[32] = {
81     /*	[offset]			reg	     bits of st mu re mk en */
82 	[SOUND_MIXER_VOLUME]	= { AC97_MIX_MASTER, 	5, 0, 1, 1, 6, 0, 1 },
83 	[SOUND_MIXER_OGAIN]	= { AC97_MIX_AUXOUT, 	5, 0, 1, 1, 0, 0, 0 },
84 	[SOUND_MIXER_PHONEOUT]	= { AC97_MIX_MONO, 	5, 0, 0, 1, 7, 0, 0 },
85 	[SOUND_MIXER_BASS]	= { AC97_MIX_TONE, 	4, 8, 0, 0, 0, 1, 0 },
86 	[SOUND_MIXER_TREBLE]	= { AC97_MIX_TONE, 	4, 0, 0, 0, 0, 1, 0 },
87 	[SOUND_MIXER_PCM]	= { AC97_MIX_PCM, 	5, 0, 1, 1, 0, 0, 1 },
88 	[SOUND_MIXER_SPEAKER]	= { AC97_MIX_BEEP, 	4, 1, 0, 1, 0, 0, 0 },
89 	[SOUND_MIXER_LINE]	= { AC97_MIX_LINE, 	5, 0, 1, 1, 5, 0, 1 },
90 	[SOUND_MIXER_PHONEIN]	= { AC97_MIX_PHONE, 	5, 0, 0, 1, 8, 0, 0 },
91 	[SOUND_MIXER_MIC] 	= { AC97_MIX_MIC, 	5, 0, 0, 1, 1, 1, 1 },
92 	/* use igain for the mic 20dB boost */
93 	[SOUND_MIXER_IGAIN] 	= { -AC97_MIX_MIC, 	1, 6, 0, 0, 0, 1, 1 },
94 	[SOUND_MIXER_CD]	= { AC97_MIX_CD, 	5, 0, 1, 1, 2, 0, 1 },
95 	[SOUND_MIXER_LINE1]	= { AC97_MIX_AUX, 	5, 0, 1, 1, 4, 0, 0 },
96 	[SOUND_MIXER_VIDEO]	= { AC97_MIX_VIDEO, 	5, 0, 1, 1, 3, 0, 0 },
97 	[SOUND_MIXER_RECLEV]	= { -AC97_MIX_RGAIN, 	4, 0, 1, 1, 0, 0, 1 }
98 };
99 
100 static const struct ac97_vendorid ac97vendorid[] = {
101 	{ 0x41445300, "Analog Devices" },
102 	{ 0x414b4d00, "Asahi Kasei" },
103 	{ 0x414c4300, "Realtek" },
104 	{ 0x414c4700, "Avance Logic" },
105 	{ 0x43525900, "Cirrus Logic" },
106 	{ 0x434d4900, "C-Media Electronics" },
107 	{ 0x43585400, "Conexant" },
108 	{ 0x44543000, "Diamond Technology" },
109 	{ 0x454d4300, "eMicro" },
110 	{ 0x45838300, "ESS Technology" },
111 	{ 0x48525300, "Intersil" },
112 	{ 0x49434500, "ICEnsemble" },
113 	{ 0x49544500, "ITE, Inc." },
114 	{ 0x4e534300, "National Semiconductor" },
115 	{ 0x50534300, "Philips Semiconductor" },
116 	{ 0x83847600, "SigmaTel" },
117 	{ 0x53494c00, "Silicon Laboratories" },
118 	{ 0x54524100, "TriTech" },
119 	{ 0x54584e00, "Texas Instruments" },
120 	{ 0x56494100, "VIA Technologies" },
121 	{ 0x57454300, "Winbond" },
122 	{ 0x574d4c00, "Wolfson" },
123 	{ 0x594d4800, "Yamaha" },
124 	/*
125 	 * XXX This is a fluke, really! The real vendor
126 	 * should be SigmaTel, not this! This should be
127 	 * removed someday!
128 	 */
129 	{ 0x01408300, "Creative" },
130 	{ 0x00000000, NULL }
131 };
132 
133 static struct ac97_codecid ac97codecid[] = {
134 	{ 0x41445303, 0x00, 0, "AD1819",	0 },
135 	{ 0x41445340, 0x00, 0, "AD1881",	0 },
136 	{ 0x41445348, 0x00, 0, "AD1881A",	0 },
137 	{ 0x41445360, 0x00, 0, "AD1885",	0 },
138 	{ 0x41445361, 0x00, 0, "AD1886", 	ad1886_patch },
139 	{ 0x41445362, 0x00, 0, "AD1887", 	0 },
140 	{ 0x41445363, 0x00, 0, "AD1886A", 	0 },
141 	{ 0x41445368, 0x00, 0, "AD1888", 	ad198x_patch },
142 	{ 0x41445370, 0x00, 0, "AD1980",	ad198x_patch },
143 	{ 0x41445372, 0x00, 0, "AD1981A",	0 },
144 	{ 0x41445374, 0x00, 0, "AD1981B",	ad1981b_patch },
145 	{ 0x41445375, 0x00, 0, "AD1985",	ad198x_patch },
146 	{ 0x41445378, 0x00, 0, "AD1986",	ad198x_patch },
147 	{ 0x414b4d00, 0x00, 1, "AK4540", 	0 },
148 	{ 0x414b4d01, 0x00, 1, "AK4542", 	0 },
149 	{ 0x414b4d02, 0x00, 1, "AK4543", 	0 },
150 	{ 0x414b4d06, 0x00, 0, "AK4544A",	0 },
151 	{ 0x454b4d07, 0x00, 0, "AK4545",	0 },
152 	{ 0x414c4320, 0x0f, 0, "ALC100",	0 },
153 	{ 0x414c4730, 0x0f, 0, "ALC101",	0 },
154 	{ 0x414c4710, 0x0f, 0, "ALC200", 	0 },
155 	{ 0x414c4740, 0x0f, 0, "ALC202", 	0 },
156 	{ 0x414c4720, 0x0f, 0, "ALC650", 	0 },
157 	{ 0x414c4752, 0x0f, 0, "ALC250",	0 },
158 	{ 0x414c4760, 0x0f, 0, "ALC655",	alc655_patch },
159 	{ 0x414c4770, 0x0f, 0, "ALC203",	0 },
160 	{ 0x414c4780, 0x0f, 0, "ALC658",	0 },
161 	{ 0x414c4790, 0x0f, 0, "ALC850",	0 },
162 	{ 0x43525900, 0x07, 0, "CS4297", 	0 },
163 	{ 0x43525910, 0x07, 0, "CS4297A", 	0 },
164 	{ 0x43525920, 0x07, 0, "CS4294/98",	0 },
165 	{ 0x4352592d, 0x07, 0, "CS4294",	0 },
166 	{ 0x43525930, 0x07, 0, "CS4299",	0 },
167 	{ 0x43525940, 0x07, 0, "CS4201",	0 },
168 	{ 0x43525958, 0x07, 0, "CS4205",	0 },
169 	{ 0x43525960, 0x07, 0, "CS4291A",	0 },
170 	{ 0x434d4961, 0x00, 0, "CMI9739",	cmi9739_patch },
171 	{ 0x434d4941, 0x00, 0, "CMI9738",	0 },
172 	{ 0x434d4978, 0x00, 0, "CMI9761",	0 },
173 	{ 0x434d4982, 0x00, 0, "CMI9761",	0 },
174 	{ 0x434d4983, 0x00, 0, "CMI9761",	0 },
175 	{ 0x43585421, 0x00, 0, "HSD11246",	0 },
176 	{ 0x43585428, 0x07, 0, "CX20468",	0 },
177 	{ 0x43585430, 0x00, 0, "CX20468-21",	0 },
178 	{ 0x44543000, 0x00, 0, "DT0398",	0 },
179 	{ 0x454d4323, 0x00, 0, "EM28023",	0 },
180 	{ 0x454d4328, 0x00, 0, "EM28028",	0 },
181 	{ 0x45838308, 0x00, 0, "ES1988",	0 }, /* Formerly ES1921(?) */
182 	{ 0x48525300, 0x00, 0, "HMP9701",	0 },
183 	{ 0x49434501, 0x00, 0, "ICE1230",	0 },
184 	{ 0x49434511, 0x00, 0, "ICE1232",	0 },
185 	{ 0x49434514, 0x00, 0, "ICE1232A",	0 },
186 	{ 0x49434551, 0x03, 0, "VT1616",	0 }, /* Via badged ICE */
187 	{ 0x49544520, 0x00, 0, "ITE2226E",	0 },
188 	{ 0x49544560, 0x07, 0, "ITE2646E",	0 }, /* XXX: patch needed */
189 	{ 0x4e534340, 0x00, 0, "LM4540",	0 }, /* Spec blank on revid */
190 	{ 0x4e534343, 0x00, 0, "LM4543",	0 }, /* Ditto */
191 	{ 0x4e534346, 0x00, 0, "LM4546A",	0 },
192 	{ 0x4e534348, 0x00, 0, "LM4548A",	0 },
193 	{ 0x4e534331, 0x00, 0, "LM4549",	0 },
194 	{ 0x4e534349, 0x00, 0, "LM4549A",	0 },
195 	{ 0x4e534350, 0x00, 0, "LM4550",	0 },
196 	{ 0x50534301, 0x00, 0, "UCB1510",	0 },
197 	{ 0x50534304, 0x00, 0, "UCB1400",	0 },
198 	{ 0x83847600, 0x00, 0, "STAC9700/83/84",	0 },
199 	{ 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 },
200 	{ 0x83847605, 0x00, 0, "STAC9704",	0 },
201 	{ 0x83847608, 0x00, 0, "STAC9708/11",	0 },
202 	{ 0x83847609, 0x00, 0, "STAC9721/23",	0 },
203 	{ 0x83847644, 0x00, 0, "STAC9744/45",	0 },
204 	{ 0x83847650, 0x00, 0, "STAC9750/51",	0 },
205 	{ 0x83847652, 0x00, 0, "STAC9752/53",	0 },
206 	{ 0x83847656, 0x00, 0, "STAC9756/57",	0 },
207 	{ 0x83847658, 0x00, 0, "STAC9758/59",	0 },
208 	{ 0x83847660, 0x00, 0, "STAC9760/61",	0 }, /* Extrapolated */
209 	{ 0x83847662, 0x00, 0, "STAC9762/63",	0 }, /* Extrapolated */
210 	{ 0x83847666, 0x00, 0, "STAC9766/67",	0 },
211 	{ 0x53494c22, 0x00, 0, "Si3036",	0 },
212 	{ 0x53494c23, 0x00, 0, "Si3038",	0 },
213 	{ 0x54524103, 0x00, 0, "TR28023",	0 }, /* Extrapolated */
214 	{ 0x54524106, 0x00, 0, "TR28026",	0 },
215 	{ 0x54524108, 0x00, 0, "TR28028",	0 },
216 	{ 0x54524123, 0x00, 0, "TR28602",	0 },
217 	{ 0x54524e03, 0x07, 0, "TLV320AIC27",	0 },
218 	{ 0x54584e20, 0x00, 0, "TLC320AD90",	0 },
219 	{ 0x56494161, 0x00, 0, "VIA1612A",      0 },
220 	{ 0x56494170, 0x00, 0, "VIA1617A",      0 },
221 	{ 0x574d4c00, 0x00, 0, "WM9701A",	0 },
222 	{ 0x574d4c03, 0x00, 0, "WM9703/4/7/8",	0 },
223 	{ 0x574d4c04, 0x00, 0, "WM9704Q",	0 },
224 	{ 0x574d4c05, 0x00, 0, "WM9705/10",	0 },
225 	{ 0x574d4d09, 0x00, 0, "WM9709",	0 },
226 	{ 0x574d4c12, 0x00, 0, "WM9711/12",	0 }, /* XXX: patch needed */
227 	{ 0x57454301, 0x00, 0, "W83971D",	0 },
228 	{ 0x594d4800, 0x00, 0, "YMF743",	0 },
229 	{ 0x594d4802, 0x00, 0, "YMF752",	0 },
230 	{ 0x594d4803, 0x00, 0, "YMF753",	0 },
231 	/*
232 	 * XXX This is a fluke, really! The real codec
233 	 * should be STAC9704, not this! This should be
234 	 * removed someday!
235 	 */
236 	{ 0x01408384, 0x00, 0, "EV1938",	0 },
237 	{ 0, 0, 0, NULL, 0 }
238 };
239 
240 static char *ac97enhancement[] = {
241 	"no 3D Stereo Enhancement",
242 	"Analog Devices Phat Stereo",
243 	"Creative Stereo Enhancement",
244 	"National Semi 3D Stereo Enhancement",
245 	"Yamaha Ymersion",
246 	"BBE 3D Stereo Enhancement",
247 	"Crystal Semi 3D Stereo Enhancement",
248 	"Qsound QXpander",
249 	"Spatializer 3D Stereo Enhancement",
250 	"SRS 3D Stereo Enhancement",
251 	"Platform Tech 3D Stereo Enhancement",
252 	"AKM 3D Audio",
253 	"Aureal Stereo Enhancement",
254 	"Aztech 3D Enhancement",
255 	"Binaura 3D Audio Enhancement",
256 	"ESS Technology Stereo Enhancement",
257 	"Harman International VMAx",
258 	"Nvidea 3D Stereo Enhancement",
259 	"Philips Incredible Sound",
260 	"Texas Instruments 3D Stereo Enhancement",
261 	"VLSI Technology 3D Stereo Enhancement",
262 	"TriTech 3D Stereo Enhancement",
263 	"Realtek 3D Stereo Enhancement",
264 	"Samsung 3D Stereo Enhancement",
265 	"Wolfson Microelectronics 3D Enhancement",
266 	"Delta Integration 3D Enhancement",
267 	"SigmaTel 3D Enhancement",
268 	"Reserved 27",
269 	"Rockwell 3D Stereo Enhancement",
270 	"Reserved 29",
271 	"Reserved 30",
272 	"Reserved 31"
273 };
274 
275 static char *ac97feature[] = {
276 	"mic channel",
277 	"reserved",
278 	"tone",
279 	"simulated stereo",
280 	"headphone",
281 	"bass boost",
282 	"18 bit DAC",
283 	"20 bit DAC",
284 	"18 bit ADC",
285 	"20 bit ADC"
286 };
287 
288 static char *ac97extfeature[] = {
289 	"variable rate PCM",
290 	"double rate PCM",
291 	"reserved 1",
292 	"variable rate mic",
293 	"reserved 2",
294 	"reserved 3",
295 	"center DAC",
296 	"surround DAC",
297 	"LFE DAC",
298 	"AMAP",
299 	"reserved 4",
300 	"reserved 5",
301 	"reserved 6",
302 	"reserved 7",
303 };
304 
305 u_int16_t
306 ac97_rdcd(struct ac97_info *codec, int reg)
307 {
308 	if (codec->flags & AC97_F_RDCD_BUG) {
309 		u_int16_t i[2], j = 100;
310 
311 		i[0] = AC97_READ(codec->methods, codec->devinfo, reg);
312 		i[1] = AC97_READ(codec->methods, codec->devinfo, reg);
313 		while (i[0] != i[1] && j)
314 			i[j-- & 1] = AC97_READ(codec->methods, codec->devinfo, reg);
315 #if 0
316 		if (j < 100) {
317 			device_printf(codec->dev, "%s(): Inconsistent register value at"
318 					" 0x%08x (retry: %d)\n", __func__, reg, 100 - j);
319 		}
320 #endif
321 		return i[!(j & 1)];
322 	}
323 	return AC97_READ(codec->methods, codec->devinfo, reg);
324 }
325 
326 void
327 ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val)
328 {
329 	AC97_WRITE(codec->methods, codec->devinfo, reg, val);
330 }
331 
332 static void
333 ac97_reset(struct ac97_info *codec)
334 {
335 	u_int32_t i, ps;
336 	ac97_wrcd(codec, AC97_REG_RESET, 0);
337 	for (i = 0; i < 500; i++) {
338 		ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS;
339 		if (ps == AC97_POWER_STATUS)
340 			return;
341 		DELAY(1000);
342 	}
343 	device_printf(codec->dev, "AC97 reset timed out.\n");
344 }
345 
346 int
347 ac97_setrate(struct ac97_info *codec, int which, int rate)
348 {
349 	u_int16_t v;
350 
351 	switch(which) {
352 	case AC97_REGEXT_FDACRATE:
353 	case AC97_REGEXT_SDACRATE:
354 	case AC97_REGEXT_LDACRATE:
355 	case AC97_REGEXT_LADCRATE:
356 	case AC97_REGEXT_MADCRATE:
357 		break;
358 
359 	default:
360 		return -1;
361 	}
362 
363 	snd_mtxlock(codec->lock);
364 	if (rate != 0) {
365 		v = rate;
366 		if (codec->extstat & AC97_EXTCAP_DRA)
367 			v >>= 1;
368 		ac97_wrcd(codec, which, v);
369 	}
370 	v = ac97_rdcd(codec, which);
371 	if (codec->extstat & AC97_EXTCAP_DRA)
372 		v <<= 1;
373 	snd_mtxunlock(codec->lock);
374 	return v;
375 }
376 
377 int
378 ac97_setextmode(struct ac97_info *codec, u_int16_t mode)
379 {
380 	mode &= AC97_EXTCAPS;
381 	if ((mode & ~codec->extcaps) != 0) {
382 		device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n",
383 			      mode);
384 		return -1;
385 	}
386 	snd_mtxlock(codec->lock);
387 	ac97_wrcd(codec, AC97_REGEXT_STAT, mode);
388 	codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
389 	snd_mtxunlock(codec->lock);
390 	return (mode == codec->extstat)? 0 : -1;
391 }
392 
393 u_int16_t
394 ac97_getextmode(struct ac97_info *codec)
395 {
396 	return codec->extstat;
397 }
398 
399 u_int16_t
400 ac97_getextcaps(struct ac97_info *codec)
401 {
402 	return codec->extcaps;
403 }
404 
405 u_int16_t
406 ac97_getcaps(struct ac97_info *codec)
407 {
408 	return codec->caps;
409 }
410 
411 u_int32_t
412 ac97_getsubvendor(struct ac97_info *codec)
413 {
414 	return codec->subvendor;
415 }
416 
417 static int
418 ac97_setrecsrc(struct ac97_info *codec, int channel)
419 {
420 	struct ac97mixtable_entry *e = &codec->mix[channel];
421 
422 	if (e->recidx > 0) {
423 		int val = e->recidx - 1;
424 		val |= val << 8;
425 		snd_mtxlock(codec->lock);
426 		ac97_wrcd(codec, AC97_REG_RECSEL, val);
427 		snd_mtxunlock(codec->lock);
428 		return 0;
429 	} else
430 		return -1;
431 }
432 
433 static int
434 ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
435 {
436 	struct ac97mixtable_entry *e = &codec->mix[channel];
437 
438 	if (e->reg && e->enable && e->bits) {
439 		int mask, max, val, reg;
440 
441 		reg = (e->reg >= 0) ? e->reg : -e->reg;	/* AC97 register    */
442 		max = (1 << e->bits) - 1;		/* actual range	    */
443 		mask = (max << 8) | max;		/* bits of interest */
444 
445 		if (!e->stereo)
446 			right = left;
447 
448 		/*
449 		 * Invert the range if the polarity requires so,
450 		 * then scale to 0..max-1 to compute the value to
451 		 * write into the codec, and scale back to 0..100
452 		 * for the return value.
453 		 */
454 		if (e->reg > 0) {
455 			left = 100 - left;
456 			right = 100 - right;
457 		}
458 
459 		left = (left * max) / 100;
460 		right = (right * max) / 100;
461 
462 		val = (left << 8) | right;
463 
464 		left = (left * 100) / max;
465 		right = (right * 100) / max;
466 
467 		if (e->reg > 0) {
468 			left = 100 - left;
469 			right = 100 - right;
470 		}
471 
472 		/*
473 		 * For mono controls, trim val and mask, also taking
474 		 * care of e->ofs (offset of control field).
475 		 */
476 		if (e->ofs) {
477 			val &= max;
478 			val <<= e->ofs;
479 			mask = (max << e->ofs);
480 		}
481 
482 		/*
483 		 * If we have a mute bit, add it to the mask and
484 		 * update val and set mute if both channels require a
485 		 * zero volume.
486 		 */
487 		if (e->mute == 1) {
488 			mask |= AC97_MUTE;
489 			if (left == 0 && right == 0)
490 				val = AC97_MUTE;
491 		}
492 
493 		/*
494 		 * If the mask bit is set, do not alter the other bits.
495 		 */
496 		snd_mtxlock(codec->lock);
497 		if (e->mask) {
498 			int cur = ac97_rdcd(codec, reg);
499 			val |= cur & ~(mask);
500 		}
501 		ac97_wrcd(codec, reg, val);
502 		snd_mtxunlock(codec->lock);
503 		return left | (right << 8);
504 	} else {
505 #if 0
506 		kprintf("ac97_setmixer: reg=%d, bits=%d, enable=%d\n", e->reg, e->bits, e->enable);
507 #endif
508 		return -1;
509 	}
510 }
511 
512 static void
513 ac97_fix_auxout(struct ac97_info *codec)
514 {
515 	int keep_ogain;
516 
517 	/*
518 	 * By default, The ac97 aux_out register (0x04) corresponds to OSS's
519 	 * OGAIN setting.
520 	 *
521 	 * We first check whether aux_out is a valid register.  If not
522 	 * we may not want to keep ogain.
523 	 */
524 	keep_ogain = ac97_rdcd(codec, AC97_MIX_AUXOUT) & 0x8000;
525 
526 	/*
527 	 * Determine what AUX_OUT really means, it can be:
528 	 *
529 	 * 1. Headphone out.
530 	 * 2. 4-Channel Out
531 	 * 3. True line level out (effectively master volume).
532 	 *
533 	 * See Sections 5.2.1 and 5.27 for AUX_OUT Options in AC97r2.{2,3}.
534 	 */
535 	if (codec->extcaps & AC97_EXTCAP_SDAC &&
536 	    ac97_rdcd(codec, AC97_MIXEXT_SURROUND) == 0x8080) {
537 		codec->mix[SOUND_MIXER_OGAIN].reg = AC97_MIXEXT_SURROUND;
538 		keep_ogain = 1;
539 	}
540 
541 	if (keep_ogain == 0) {
542 		bzero(&codec->mix[SOUND_MIXER_OGAIN],
543 		      sizeof(codec->mix[SOUND_MIXER_OGAIN]));
544 	}
545 }
546 
547 static void
548 ac97_fix_tone(struct ac97_info *codec)
549 {
550 	/*
551 	 * YMF chips does not indicate tone and 3D enhancement capability
552 	 * in the AC97_REG_RESET register.
553 	 */
554 	switch (codec->id) {
555 	case 0x594d4800:	/* YMF743 */
556 	case 0x594d4803:	/* YMF753 */
557 		codec->caps |= AC97_CAP_TONE;
558 		codec->se |= 0x04;
559 		break;
560 	case 0x594d4802:	/* YMF752 */
561 		codec->se |= 0x04;
562 		break;
563 	default:
564 		break;
565 	}
566 
567 	/* Hide treble and bass if they don't exist */
568 	if ((codec->caps & AC97_CAP_TONE) == 0) {
569 		bzero(&codec->mix[SOUND_MIXER_BASS],
570 		      sizeof(codec->mix[SOUND_MIXER_BASS]));
571 		bzero(&codec->mix[SOUND_MIXER_TREBLE],
572 		      sizeof(codec->mix[SOUND_MIXER_TREBLE]));
573 	}
574 }
575 
576 static const char*
577 ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
578 {
579 	if (cname == NULL) {
580 		ksprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
581 		return buf;
582 	}
583 
584 	if (vname == NULL) vname = "Unknown";
585 
586 	if (bootverbose) {
587 		ksprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
588 	} else {
589 		ksprintf(buf, "%s %s AC97 Codec", vname, cname);
590 	}
591 	return buf;
592 }
593 
594 static unsigned
595 ac97_initmixer(struct ac97_info *codec)
596 {
597 	ac97_patch codec_patch;
598 	const char *cname, *vname;
599 	char desc[80];
600 	u_int8_t model, step;
601 	unsigned i, j, k, bit, old;
602 	u_int32_t id;
603 	int reg;
604 
605 	snd_mtxlock(codec->lock);
606 	codec->count = AC97_INIT(codec->methods, codec->devinfo);
607 	if (codec->count == 0) {
608 		device_printf(codec->dev, "ac97 codec init failed\n");
609 		snd_mtxunlock(codec->lock);
610 		return ENODEV;
611 	}
612 
613 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
614 	ac97_reset(codec);
615 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
616 
617 	i = ac97_rdcd(codec, AC97_REG_RESET);
618 	j = 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) {
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 < 32; 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 < 32; 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 		kprintf("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 				kprintf("%s%s", j++? ", " : "", ac97feature[i]);
761 		kprintf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
762 		kprintf("%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 				kprintf(" extended features ");
769 			for (i = j = 0; i < 14; i++)
770 				if (codec->extcaps & (1 << i))
771 					kprintf("%s%s", j++? ", " : "", ac97extfeature[i]);
772 			kprintf("\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 
826 	codec = (struct ac97_info *)kmalloc(sizeof *codec, M_AC97, M_WAITOK);
827 	if (codec == NULL)
828 		return NULL;
829 
830 	ksnprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev));
831 	codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
832 	codec->methods = kobj_create(cls, M_AC97, M_WAITOK);
833 	if (codec->methods == NULL) {
834 		snd_mtxfree(codec->lock);
835 		kfree(codec, M_AC97);
836 		return NULL;
837 	}
838 
839 	codec->dev = dev;
840 	codec->devinfo = devinfo;
841 	codec->flags = 0;
842 	return codec;
843 }
844 
845 void
846 ac97_destroy(struct ac97_info *codec)
847 {
848 	if (codec->methods != NULL)
849 		kobj_delete(codec->methods, M_AC97);
850 	snd_mtxfree(codec->lock);
851 	kfree(codec, M_AC97);
852 }
853 
854 void
855 ac97_setflags(struct ac97_info *codec, u_int32_t val)
856 {
857 	codec->flags = val;
858 }
859 
860 u_int32_t
861 ac97_getflags(struct ac97_info *codec)
862 {
863 	return codec->flags;
864 }
865 
866 /* -------------------------------------------------------------------- */
867 
868 static int
869 ac97mix_init(struct snd_mixer *m)
870 {
871 	struct ac97_info *codec = mix_getdevinfo(m);
872 	u_int32_t i, mask;
873 
874 	if (codec == NULL)
875 		return -1;
876 
877 	if (ac97_initmixer(codec))
878 		return -1;
879 
880 	switch (codec->id) {
881 	case 0x41445374:	/* AD1981B */
882 		switch (codec->subvendor) {
883 		case 0x02d91014:
884 			/*
885 			 * IBM Thinkcentre:
886 			 *
887 			 * Tie "ogain" and "phout" to "vol" since its
888 			 * master volume is basically useless and can't
889 			 * control anything.
890 			 */
891 			mask = 0;
892 			if (codec->mix[SOUND_MIXER_OGAIN].enable)
893 				mask |= SOUND_MASK_OGAIN;
894 			if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
895 				mask |= SOUND_MASK_PHONEOUT;
896 			if (codec->mix[SOUND_MIXER_VOLUME].enable)
897 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
898 				    mask);
899 			else {
900 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
901 				    mask);
902 				mix_setrealdev(m, SOUND_MIXER_VOLUME,
903 				    SOUND_MIXER_NONE);
904 			}
905 			break;
906 		case 0x099c103c:
907 			/*
908 			 * HP nx6110:
909 			 *
910 			 * By default, "vol" is controlling internal speakers
911 			 * (not a master volume!) and "ogain" is controlling
912 			 * headphone. Enable dummy "phout" so it can be
913 			 * remapped to internal speakers and virtualize
914 			 * "vol" to control both.
915 			 */
916 			codec->mix[SOUND_MIXER_OGAIN].enable = 1;
917 			codec->mix[SOUND_MIXER_PHONEOUT].enable = 1;
918 			mix_setrealdev(m, SOUND_MIXER_PHONEOUT,
919 			    SOUND_MIXER_VOLUME);
920 			mix_setrealdev(m, SOUND_MIXER_VOLUME,
921 			    SOUND_MIXER_NONE);
922 			mix_setparentchild(m, SOUND_MIXER_VOLUME,
923 			    SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT);
924 			break;
925 		default:
926 			break;
927 		}
928 		break;
929 	case 0x434d4941:	/* CMI9738 */
930 	case 0x434d4961:	/* CMI9739 */
931 	case 0x434d4978:	/* CMI9761 */
932 	case 0x434d4982:	/* CMI9761 */
933 	case 0x434d4983:	/* CMI9761 */
934 		ac97_wrcd(codec, AC97_MIX_PCM, 0);
935 		bzero(&codec->mix[SOUND_MIXER_PCM],
936 		    sizeof(codec->mix[SOUND_MIXER_PCM]));
937 		pcm_setflags(codec->dev, pcm_getflags(codec->dev) |
938 		    SD_F_SOFTPCMVOL);
939 		/* XXX How about master volume ? */
940 		break;
941 	default:
942 		break;
943 	}
944 
945 #if 0
946 	/* XXX For the sake of debugging purposes */
947 	mix_setparentchild(m, SOUND_MIXER_VOLUME,
948 	    SOUND_MASK_PCM | SOUND_MASK_CD);
949 	mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
950 	ac97_wrcd(codec, AC97_MIX_MASTER, 0);
951 #endif
952 
953 	mask = 0;
954 	for (i = 0; i < 32; i++)
955 		mask |= codec->mix[i].enable? 1 << i : 0;
956 	mix_setdevs(m, mask);
957 
958 	mask = 0;
959 	for (i = 0; i < 32; i++)
960 		mask |= codec->mix[i].recidx? 1 << i : 0;
961 	mix_setrecdevs(m, mask);
962 	return 0;
963 }
964 
965 static int
966 ac97mix_uninit(struct snd_mixer *m)
967 {
968 	struct ac97_info *codec = mix_getdevinfo(m);
969 
970 	if (codec == NULL)
971 		return -1;
972 	/*
973 	if (ac97_uninitmixer(codec))
974 		return -1;
975 	*/
976 	ac97_destroy(codec);
977 	return 0;
978 }
979 
980 static int
981 ac97mix_reinit(struct snd_mixer *m)
982 {
983 	struct ac97_info *codec = mix_getdevinfo(m);
984 
985 	if (codec == NULL)
986 		return -1;
987 	return ac97_reinitmixer(codec);
988 }
989 
990 static int
991 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
992 {
993 	struct ac97_info *codec = mix_getdevinfo(m);
994 
995 	if (codec == NULL)
996 		return -1;
997 	return ac97_setmixer(codec, dev, left, right);
998 }
999 
1000 static int
1001 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1002 {
1003 	int i;
1004 	struct ac97_info *codec = mix_getdevinfo(m);
1005 
1006 	if (codec == NULL)
1007 		return -1;
1008 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1009 		if ((src & (1 << i)) != 0)
1010 			break;
1011 	return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
1012 }
1013 
1014 static kobj_method_t ac97mixer_methods[] = {
1015     	KOBJMETHOD(mixer_init,		ac97mix_init),
1016     	KOBJMETHOD(mixer_uninit,	ac97mix_uninit),
1017     	KOBJMETHOD(mixer_reinit,	ac97mix_reinit),
1018     	KOBJMETHOD(mixer_set,		ac97mix_set),
1019     	KOBJMETHOD(mixer_setrecsrc,	ac97mix_setrecsrc),
1020 	KOBJMETHOD_END
1021 };
1022 MIXER_DECLARE(ac97mixer);
1023 
1024 /* -------------------------------------------------------------------- */
1025 
1026 kobj_class_t
1027 ac97_getmixerclass(void)
1028 {
1029 	return &ac97mixer_class;
1030 }
1031