xref: /dragonfly/sys/dev/sound/pcm/ac97.c (revision 9b5a9965)
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.5 2007/05/13 20:53:39 ariff Exp $
27  * $DragonFly: src/sys/dev/sound/pcm/ac97.c,v 1.25 2007/06/16 20:07:22 dillon 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.25 2007/06/16 20:07:22 dillon 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 void
578 ac97_fix_volume(struct ac97_info *codec)
579 {
580     	struct snddev_info *d = device_get_softc(codec->dev);
581 
582 #if 0
583 	/* XXX For the sake of debugging purposes */
584 	ac97_wrcd(codec, AC97_MIX_PCM, 0);
585 	bzero(&codec->mix[SOUND_MIXER_PCM],
586 		sizeof(codec->mix[SOUND_MIXER_PCM]));
587 	if (d)
588 		d->flags |= SD_F_SOFTPCMVOL;
589 	return;
590 #endif
591 	switch (codec->id) {
592 		case 0x434d4941:	/* CMI9738 */
593 		case 0x434d4961:	/* CMI9739 */
594 		case 0x434d4978:	/* CMI9761 */
595 		case 0x434d4982:	/* CMI9761 */
596 		case 0x434d4983:	/* CMI9761 */
597 			ac97_wrcd(codec, AC97_MIX_PCM, 0);
598 			break;
599 		default:
600 			return;
601 			break;
602 	}
603 	bzero(&codec->mix[SOUND_MIXER_PCM],
604 			sizeof(codec->mix[SOUND_MIXER_PCM]));
605 	if (d)
606 		d->flags |= SD_F_SOFTPCMVOL;
607 }
608 
609 static const char*
610 ac97_hw_desc(u_int32_t id, const char* vname, const char* cname, char* buf)
611 {
612 	if (cname == NULL) {
613 		ksprintf(buf, "Unknown AC97 Codec (id = 0x%08x)", id);
614 		return buf;
615 	}
616 
617 	if (vname == NULL) vname = "Unknown";
618 
619 	if (bootverbose) {
620 		ksprintf(buf, "%s %s AC97 Codec (id = 0x%08x)", vname, cname, id);
621 	} else {
622 		ksprintf(buf, "%s %s AC97 Codec", vname, cname);
623 	}
624 	return buf;
625 }
626 
627 static unsigned
628 ac97_initmixer(struct ac97_info *codec)
629 {
630 	ac97_patch codec_patch;
631 	const char *cname, *vname;
632 	char desc[80];
633 	u_int8_t model, step;
634 	unsigned i, j, k, bit, old;
635 	u_int32_t id;
636 	int reg;
637 
638 	snd_mtxlock(codec->lock);
639 	codec->count = AC97_INIT(codec->methods, codec->devinfo);
640 	if (codec->count == 0) {
641 		device_printf(codec->dev, "ac97 codec init failed\n");
642 		snd_mtxunlock(codec->lock);
643 		return ENODEV;
644 	}
645 
646 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
647 	ac97_reset(codec);
648 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
649 
650 	i = ac97_rdcd(codec, AC97_REG_RESET);
651 	j = ac97_rdcd(codec, AC97_REG_RESET);
652 	/*
653 	 * Let see if this codec can return consistent value.
654 	 * If not, turn on aggressive read workaround
655 	 * (STAC9704 comes in mind).
656 	 */
657 	if (i != j) {
658 		codec->flags |= AC97_F_RDCD_BUG;
659 		i = ac97_rdcd(codec, AC97_REG_RESET);
660 	}
661 	codec->caps = i & 0x03ff;
662 	codec->se =  (i & 0x7c00) >> 10;
663 
664 	id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2);
665 	if (id == 0 || id == 0xffffffff) {
666 		device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id);
667 		snd_mtxunlock(codec->lock);
668 		return ENODEV;
669 	}
670 
671 	codec->id = id;
672 	codec->subvendor = (u_int32_t)pci_get_subdevice(codec->dev) << 16;
673 	codec->subvendor |= (u_int32_t)pci_get_subvendor(codec->dev) &
674 	    0x0000ffff;
675 	codec->noext = 0;
676 	codec_patch = NULL;
677 
678 	cname = NULL;
679 	model = step = 0;
680 	for (i = 0; ac97codecid[i].id; i++) {
681 		u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask;
682 		if ((ac97codecid[i].id & modelmask) == (id & modelmask)) {
683 			codec->noext = ac97codecid[i].noext;
684 			codec_patch = ac97codecid[i].patch;
685 			cname = ac97codecid[i].name;
686 			model = (id & modelmask) & 0xff;
687 			step = (id & ~modelmask) & 0xff;
688 			break;
689 		}
690 	}
691 
692 	vname = NULL;
693 	for (i = 0; ac97vendorid[i].id; i++) {
694 		if (ac97vendorid[i].id == (id & 0xffffff00)) {
695 			vname = ac97vendorid[i].name;
696 			break;
697 		}
698 	}
699 
700 	codec->extcaps = 0;
701 	codec->extid = 0;
702 	codec->extstat = 0;
703 	if (!codec->noext) {
704 		i = ac97_rdcd(codec, AC97_REGEXT_ID);
705 		if (i != 0xffff) {
706 			codec->extcaps = i & 0x3fff;
707 			codec->extid =  (i & 0xc000) >> 14;
708 			codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
709 		}
710 	}
711 
712 	for (i = 0; i < 32; i++) {
713 		codec->mix[i] = ac97mixtable_default[i];
714 	}
715 	ac97_fix_auxout(codec);
716 	ac97_fix_tone(codec);
717 	ac97_fix_volume(codec);
718 	if (codec_patch)
719 		codec_patch(codec);
720 
721 	for (i = 0; i < 32; i++) {
722 		k = codec->noext? codec->mix[i].enable : 1;
723 		reg = codec->mix[i].reg;
724 		if (reg < 0)
725 			reg = -reg;
726 		if (k && reg) {
727 			j = old = ac97_rdcd(codec, reg);
728 			/*
729 			 * Test for mute bit (except for AC97_MIX_TONE,
730 			 * where we simply assume it as available).
731 			 */
732 			if (codec->mix[i].mute) {
733 				ac97_wrcd(codec, reg, j | 0x8000);
734 				j = ac97_rdcd(codec, reg);
735 			} else
736 				j |= 0x8000;
737 			if ((j & 0x8000)) {
738 				/*
739 				 * Test whether the control width should be
740 				 * 4, 5 or 6 bit. For 5bit register, we should
741 				 * test it whether it's really 5 or 6bit. Leave
742 				 * 4bit register alone, because sometimes an
743 				 * attempt to write past 4th bit may cause
744 				 * incorrect result especially for AC97_MIX_BEEP
745 				 * (ac97 2.3).
746 				 */
747 				bit = codec->mix[i].bits;
748 				if (bit == 5)
749 					bit++;
750 				j = ((1 << bit) - 1) << codec->mix[i].ofs;
751 				ac97_wrcd(codec, reg,
752 					j | (codec->mix[i].mute ? 0x8000 : 0));
753 				k = ac97_rdcd(codec, reg) & j;
754 				k >>= codec->mix[i].ofs;
755 				if (reg == AC97_MIX_TONE &&
756 							((k & 0x0001) == 0x0000))
757 					k >>= 1;
758 				for (j = 0; k >> j; j++)
759 					;
760 				if (j != 0) {
761 #if 0
762 					device_printf(codec->dev, "%2d: [ac97_rdcd() = %d] [Testbit = %d] %d -> %d\n",
763 						i, k, bit, codec->mix[i].bits, j);
764 #endif
765 					codec->mix[i].enable = 1;
766 					codec->mix[i].bits = j;
767 				} else if (reg == AC97_MIX_BEEP) {
768 					/*
769 					 * Few codec such as CX20468-21 does
770 					 * have this control register, although
771 					 * the only usable part is the mute bit.
772 					 */
773 					codec->mix[i].enable = 1;
774 				} else
775 					codec->mix[i].enable = 0;
776 			} else
777 				codec->mix[i].enable = 0;
778 			ac97_wrcd(codec, reg, old);
779 		}
780 #if 0
781 		kprintf("mixch %d, en=%d, b=%d\n", i, codec->mix[i].enable, codec->mix[i].bits);
782 #endif
783 	}
784 
785 	device_printf(codec->dev, "<%s>\n",
786 		      ac97_hw_desc(codec->id, vname, cname, desc));
787 
788 	if (bootverbose) {
789 		if (codec->flags & AC97_F_RDCD_BUG)
790 			device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
791 		device_printf(codec->dev, "Codec features ");
792 		for (i = j = 0; i < 10; i++)
793 			if (codec->caps & (1 << i))
794 				kprintf("%s%s", j++? ", " : "", ac97feature[i]);
795 		kprintf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
796 		kprintf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]);
797 
798 		if (codec->extcaps != 0 || codec->extid) {
799 			device_printf(codec->dev, "%s codec",
800 				      codec->extid? "Secondary" : "Primary");
801 			if (codec->extcaps)
802 				kprintf(" extended features ");
803 			for (i = j = 0; i < 14; i++)
804 				if (codec->extcaps & (1 << i))
805 					kprintf("%s%s", j++? ", " : "", ac97extfeature[i]);
806 			kprintf("\n");
807 		}
808 	}
809 
810 	i = 0;
811 	while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
812 		if (++i == 100) {
813 			device_printf(codec->dev, "ac97 codec reports dac not ready\n");
814 			break;
815 		}
816 		DELAY(1000);
817 	}
818 	if (bootverbose)
819 		device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i);
820 	snd_mtxunlock(codec->lock);
821 	return 0;
822 }
823 
824 static unsigned
825 ac97_reinitmixer(struct ac97_info *codec)
826 {
827 	snd_mtxlock(codec->lock);
828 	codec->count = AC97_INIT(codec->methods, codec->devinfo);
829 	if (codec->count == 0) {
830 		device_printf(codec->dev, "ac97 codec init failed\n");
831 		snd_mtxunlock(codec->lock);
832 		return ENODEV;
833 	}
834 
835 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
836 	ac97_reset(codec);
837 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
838 
839 	if (!codec->noext) {
840 		ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat);
841 		if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS)
842 		    != codec->extstat)
843 			device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n",
844 				      codec->extstat,
845 				      ac97_rdcd(codec, AC97_REGEXT_STAT) &
846 				      AC97_EXTCAPS);
847 	}
848 
849 	if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
850 		device_printf(codec->dev, "ac97 codec reports dac not ready\n");
851 	snd_mtxunlock(codec->lock);
852 	return 0;
853 }
854 
855 struct ac97_info *
856 ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
857 {
858 	struct ac97_info *codec;
859 
860 	codec = (struct ac97_info *)kmalloc(sizeof *codec, M_AC97, M_NOWAIT);
861 	if (codec == NULL)
862 		return NULL;
863 
864 	ksnprintf(codec->name, AC97_NAMELEN, "%s:ac97", device_get_nameunit(dev));
865 	codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
866 	codec->methods = kobj_create(cls, M_AC97, M_WAITOK);
867 	if (codec->methods == NULL) {
868 		snd_mtxfree(codec->lock);
869 		kfree(codec, M_AC97);
870 		return NULL;
871 	}
872 
873 	codec->dev = dev;
874 	codec->devinfo = devinfo;
875 	codec->flags = 0;
876 	return codec;
877 }
878 
879 void
880 ac97_destroy(struct ac97_info *codec)
881 {
882 	if (codec->methods != NULL)
883 		kobj_delete(codec->methods, M_AC97);
884 	snd_mtxfree(codec->lock);
885 	kfree(codec, M_AC97);
886 }
887 
888 void
889 ac97_setflags(struct ac97_info *codec, u_int32_t val)
890 {
891 	codec->flags = val;
892 }
893 
894 u_int32_t
895 ac97_getflags(struct ac97_info *codec)
896 {
897 	return codec->flags;
898 }
899 
900 /* -------------------------------------------------------------------- */
901 
902 static int
903 ac97mix_init(struct snd_mixer *m)
904 {
905 	struct ac97_info *codec = mix_getdevinfo(m);
906 	u_int32_t i, mask;
907 
908 	if (codec == NULL)
909 		return -1;
910 
911 	if (ac97_initmixer(codec))
912 		return -1;
913 
914 	mask = 0;
915 	for (i = 0; i < 32; i++)
916 		mask |= codec->mix[i].enable? 1 << i : 0;
917 	mix_setdevs(m, mask);
918 
919 	mask = 0;
920 	for (i = 0; i < 32; i++)
921 		mask |= codec->mix[i].recidx? 1 << i : 0;
922 	mix_setrecdevs(m, mask);
923 	return 0;
924 }
925 
926 static int
927 ac97mix_uninit(struct snd_mixer *m)
928 {
929 	struct ac97_info *codec = mix_getdevinfo(m);
930 
931 	if (codec == NULL)
932 		return -1;
933 	/*
934 	if (ac97_uninitmixer(codec))
935 		return -1;
936 	*/
937 	ac97_destroy(codec);
938 	return 0;
939 }
940 
941 static int
942 ac97mix_reinit(struct snd_mixer *m)
943 {
944 	struct ac97_info *codec = mix_getdevinfo(m);
945 
946 	if (codec == NULL)
947 		return -1;
948 	return ac97_reinitmixer(codec);
949 }
950 
951 static int
952 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
953 {
954 	struct ac97_info *codec = mix_getdevinfo(m);
955 
956 	if (codec == NULL)
957 		return -1;
958 	return ac97_setmixer(codec, dev, left, right);
959 }
960 
961 static int
962 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
963 {
964 	int i;
965 	struct ac97_info *codec = mix_getdevinfo(m);
966 
967 	if (codec == NULL)
968 		return -1;
969 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
970 		if ((src & (1 << i)) != 0)
971 			break;
972 	return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
973 }
974 
975 static kobj_method_t ac97mixer_methods[] = {
976     	KOBJMETHOD(mixer_init,		ac97mix_init),
977     	KOBJMETHOD(mixer_uninit,	ac97mix_uninit),
978     	KOBJMETHOD(mixer_reinit,	ac97mix_reinit),
979     	KOBJMETHOD(mixer_set,		ac97mix_set),
980     	KOBJMETHOD(mixer_setrecsrc,	ac97mix_setrecsrc),
981 	{ 0, 0 }
982 };
983 MIXER_DECLARE(ac97mixer);
984 
985 /* -------------------------------------------------------------------- */
986 
987 kobj_class_t
988 ac97_getmixerclass(void)
989 {
990 	return &ac97mixer_class;
991 }
992