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