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