xref: /freebsd/sys/dev/sound/pcm/ac97.c (revision f0a75d274af375d15b97b830966b99a02b7db911)
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 	codec->dev = dev;
823 	codec->devinfo = devinfo;
824 	codec->flags = 0;
825 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
826 		    "eapdinv", &eapdinv) == 0) {
827 		if (eapdinv != 0)
828 			codec->flags |= AC97_F_EAPD_INV;
829 	}
830 	return codec;
831 }
832 
833 void
834 ac97_destroy(struct ac97_info *codec)
835 {
836 	snd_mtxlock(codec->lock);
837 	if (codec->methods != NULL)
838 		kobj_delete(codec->methods, M_AC97);
839 	snd_mtxfree(codec->lock);
840 	free(codec, M_AC97);
841 }
842 
843 void
844 ac97_setflags(struct ac97_info *codec, u_int32_t val)
845 {
846 	codec->flags = val;
847 }
848 
849 u_int32_t
850 ac97_getflags(struct ac97_info *codec)
851 {
852 	return codec->flags;
853 }
854 
855 /* -------------------------------------------------------------------- */
856 
857 #ifdef SND_DYNSYSCTL
858 static int
859 sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)
860 {
861 	struct ac97_info *codec;
862 	int ea, inv, err = 0;
863 	u_int16_t val;
864 
865 	codec = oidp->oid_arg1;
866 	if (codec == NULL || codec->id == 0 || codec->lock == NULL)
867 		return EINVAL;
868 	snd_mtxlock(codec->lock);
869 	val = ac97_rdcd(codec, AC97_REG_POWER);
870 	inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1;
871 	ea = (val >> 15) ^ inv;
872 	snd_mtxunlock(codec->lock);
873 	err = sysctl_handle_int(oidp, &ea, sizeof(ea), req);
874 	if (err == 0 && req->newptr != NULL) {
875 		if (ea != 0 && ea != 1)
876 			return EINVAL;
877 		if (ea != ((val >> 15) ^ inv)) {
878 			snd_mtxlock(codec->lock);
879 			ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000);
880 			snd_mtxunlock(codec->lock);
881 		}
882 	}
883 	return err;
884 }
885 #endif
886 
887 static void
888 ac97_init_sysctl(struct ac97_info *codec)
889 {
890 #ifdef SND_DYNSYSCTL
891 	u_int16_t orig, val;
892 
893 	if (codec == NULL || codec->dev == NULL)
894 		return;
895 	snd_mtxlock(codec->lock);
896 	orig = ac97_rdcd(codec, AC97_REG_POWER);
897 	ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000);
898 	val = ac97_rdcd(codec, AC97_REG_POWER);
899 	ac97_wrcd(codec, AC97_REG_POWER, orig);
900 	snd_mtxunlock(codec->lock);
901 	if ((val & 0x8000) == (orig & 0x8000))
902 		return;
903 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev),
904 	    SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)),
905             OID_AUTO, "eapd", CTLTYPE_INT | CTLFLAG_RW,
906 	    codec, sizeof(codec), sysctl_hw_snd_ac97_eapd,
907 	    "I", "AC97 External Amplifier");
908 #endif
909 }
910 
911 static int
912 ac97mix_init(struct snd_mixer *m)
913 {
914 	struct ac97_info *codec = mix_getdevinfo(m);
915 	struct snddev_info *d;
916 	u_int32_t subvendor;
917 	u_int32_t i, mask;
918 
919 	if (codec == NULL)
920 		return -1;
921 
922 	if (ac97_initmixer(codec))
923 		return -1;
924 
925 	switch (codec->id) {
926 	case 0x41445374:	/* AD1981B */
927 		subvendor = (u_int32_t)pci_get_subdevice(codec->dev) << 16;
928 		subvendor |= (u_int32_t)pci_get_subvendor(codec->dev) &
929 		    0x0000ffff;
930 		/* IBM Thinkcentre */
931 		if (subvendor == 0x02d91014) {
932 			/* Enable headphone jack sensing */
933 			ac97_wrcd(codec, 0x72, ac97_rdcd(codec, 0x72) |
934 			    0x0800);
935 			mask = 0;
936 			if (codec->mix[SOUND_MIXER_OGAIN].enable)
937 				mask |= SOUND_MASK_OGAIN;
938 			if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
939 				mask |= SOUND_MASK_PHONEOUT;
940 			/* Tie ogain/phone to master volume */
941 			if (codec->mix[SOUND_MIXER_VOLUME].enable)
942 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
943 				    mask);
944 			else {
945 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
946 				    mask);
947 				mix_setrealdev(m, SOUND_MIXER_VOLUME,
948 				    SOUND_MIXER_NONE);
949 			}
950 		}
951 		break;
952 	case 0x434d4941:	/* CMI9738 */
953 	case 0x434d4961:	/* CMI9739 */
954 	case 0x434d4978:	/* CMI9761 */
955 	case 0x434d4982:	/* CMI9761 */
956 	case 0x434d4983:	/* CMI9761 */
957 		ac97_wrcd(codec, AC97_MIX_PCM, 0);
958 		bzero(&codec->mix[SOUND_MIXER_PCM],
959 		    sizeof(codec->mix[SOUND_MIXER_PCM]));
960 		d = device_get_softc(codec->dev);
961 		if (d != NULL)
962 			d->flags |= SD_F_SOFTPCMVOL;
963 		/* XXX How about master volume ? */
964 		break;
965 	default:
966 		break;
967 	}
968 
969 #if 0
970 	/* XXX For the sake of debugging purposes */
971 	mix_setparentchild(m, SOUND_MIXER_VOLUME,
972 	    SOUND_MASK_PCM | SOUND_MASK_CD);
973 	mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
974 	ac97_wrcd(codec, AC97_MIX_MASTER, 0);
975 #endif
976 
977 	mask = 0;
978 	for (i = 0; i < 32; i++)
979 		mask |= codec->mix[i].enable? 1 << i : 0;
980 	mix_setdevs(m, mask);
981 
982 	mask = 0;
983 	for (i = 0; i < 32; i++)
984 		mask |= codec->mix[i].recidx? 1 << i : 0;
985 	mix_setrecdevs(m, mask);
986 
987 	ac97_init_sysctl(codec);
988 
989 	return 0;
990 }
991 
992 static int
993 ac97mix_uninit(struct snd_mixer *m)
994 {
995 	struct ac97_info *codec = mix_getdevinfo(m);
996 
997 	if (codec == NULL)
998 		return -1;
999 	/*
1000 	if (ac97_uninitmixer(codec))
1001 		return -1;
1002 	*/
1003 	ac97_destroy(codec);
1004 	return 0;
1005 }
1006 
1007 static int
1008 ac97mix_reinit(struct snd_mixer *m)
1009 {
1010 	struct ac97_info *codec = mix_getdevinfo(m);
1011 
1012 	if (codec == NULL)
1013 		return -1;
1014 	return ac97_reinitmixer(codec);
1015 }
1016 
1017 static int
1018 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1019 {
1020 	struct ac97_info *codec = mix_getdevinfo(m);
1021 
1022 	if (codec == NULL)
1023 		return -1;
1024 	return ac97_setmixer(codec, dev, left, right);
1025 }
1026 
1027 static int
1028 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1029 {
1030 	int i;
1031 	struct ac97_info *codec = mix_getdevinfo(m);
1032 
1033 	if (codec == NULL)
1034 		return -1;
1035 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1036 		if ((src & (1 << i)) != 0)
1037 			break;
1038 	return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
1039 }
1040 
1041 static kobj_method_t ac97mixer_methods[] = {
1042     	KOBJMETHOD(mixer_init,		ac97mix_init),
1043     	KOBJMETHOD(mixer_uninit,	ac97mix_uninit),
1044     	KOBJMETHOD(mixer_reinit,	ac97mix_reinit),
1045     	KOBJMETHOD(mixer_set,		ac97mix_set),
1046     	KOBJMETHOD(mixer_setrecsrc,	ac97mix_setrecsrc),
1047 	{ 0, 0 }
1048 };
1049 MIXER_DECLARE(ac97mixer);
1050 
1051 /* -------------------------------------------------------------------- */
1052 
1053 kobj_class_t
1054 ac97_getmixerclass(void)
1055 {
1056 	return &ac97mixer_class;
1057 }
1058