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