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