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