xref: /src/sys/dev/sound/pcm/ac97.c (revision d048cec5fb41cf9529dd0b637a51c7ee72b59b3b)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #ifdef HAVE_KERNEL_OPTION_HEADERS
30 #include "opt_snd.h"
31 #endif
32 
33 #include <dev/sound/pcm/sound.h>
34 #include <dev/sound/pcm/ac97.h>
35 
36 #include <dev/pci/pcivar.h>
37 
38 #include "mixer_if.h"
39 
40 static MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
41 
42 typedef void (*ac97_patch)(struct ac97_info *);
43 
44 struct ac97mixtable_entry {
45 	int reg;		/* register index		*/
46 				/* reg < 0 if inverted polarity	*/
47 	unsigned bits:4;	/* width of control field	*/
48 	unsigned ofs:4;		/* offset (only if stereo=0)	*/
49 	unsigned stereo:1;	/* set for stereo controls	*/
50 	unsigned mute:1;	/* bit15 is MUTE		*/
51 	unsigned recidx:4;	/* index in rec mux		*/
52 	unsigned mask:1;	/* use only masked bits		*/
53 	unsigned enable:1;	/* entry is enabled		*/
54 };
55 
56 #define AC97_MIXER_SIZE		SOUND_MIXER_NRDEVICES
57 
58 struct ac97_info {
59 	kobj_t methods;
60 	device_t dev;
61 	void *devinfo;
62 	u_int32_t id;
63 	u_int32_t subvendor;
64 	unsigned count, caps, se, extcaps, extid, extstat, noext:1;
65 	u_int32_t flags;
66 	struct ac97mixtable_entry mix[AC97_MIXER_SIZE];
67 	char name[16];
68 	struct mtx lock;
69 };
70 
71 struct ac97_vendorid {
72 	u_int32_t   id;
73 	const char *name;
74 };
75 
76 struct ac97_codecid {
77 	u_int32_t  id;
78 	u_int8_t   stepmask;
79 	u_int8_t   noext:1;
80 	char 	  *name;
81 	ac97_patch patch;
82 };
83 
84 static const struct ac97mixtable_entry ac97mixtable_default[AC97_MIXER_SIZE] = {
85     /*	[offset]			reg	     bits of st mu re mk en */
86 	[SOUND_MIXER_VOLUME]	= { AC97_MIX_MASTER, 	5, 0, 1, 1, 6, 0, 1 },
87 	[SOUND_MIXER_OGAIN]	= { AC97_MIX_AUXOUT, 	5, 0, 1, 1, 0, 0, 0 },
88 	[SOUND_MIXER_PHONEOUT]	= { AC97_MIX_MONO, 	5, 0, 0, 1, 7, 0, 0 },
89 	[SOUND_MIXER_BASS]	= { AC97_MIX_TONE, 	4, 8, 0, 0, 0, 1, 0 },
90 	[SOUND_MIXER_TREBLE]	= { AC97_MIX_TONE, 	4, 0, 0, 0, 0, 1, 0 },
91 	[SOUND_MIXER_PCM]	= { AC97_MIX_PCM, 	5, 0, 1, 1, 0, 0, 1 },
92 	[SOUND_MIXER_SPEAKER]	= { AC97_MIX_BEEP, 	4, 1, 0, 1, 0, 0, 0 },
93 	[SOUND_MIXER_LINE]	= { AC97_MIX_LINE, 	5, 0, 1, 1, 5, 0, 1 },
94 	[SOUND_MIXER_PHONEIN]	= { AC97_MIX_PHONE, 	5, 0, 0, 1, 8, 0, 0 },
95 	[SOUND_MIXER_MIC] 	= { AC97_MIX_MIC, 	5, 0, 0, 1, 1, 1, 1 },
96 	/* use igain for the mic 20dB boost */
97 	[SOUND_MIXER_IGAIN] 	= { -AC97_MIX_MIC, 	1, 6, 0, 0, 0, 1, 1 },
98 	[SOUND_MIXER_CD]	= { AC97_MIX_CD, 	5, 0, 1, 1, 2, 0, 1 },
99 	[SOUND_MIXER_LINE1]	= { AC97_MIX_AUX, 	5, 0, 1, 1, 4, 0, 0 },
100 	[SOUND_MIXER_VIDEO]	= { AC97_MIX_VIDEO, 	5, 0, 1, 1, 3, 0, 0 },
101 	[SOUND_MIXER_RECLEV]	= { -AC97_MIX_RGAIN, 	4, 0, 1, 1, 0, 0, 1 }
102 };
103 
104 static const struct ac97_vendorid ac97vendorid[] = {
105 	{ 0x41445300, "Analog Devices" },
106 	{ 0x414b4d00, "Asahi Kasei" },
107 	{ 0x414c4300, "Realtek" },
108 	{ 0x414c4700, "Avance Logic" },
109 	{ 0x43525900, "Cirrus Logic" },
110 	{ 0x434d4900, "C-Media Electronics" },
111 	{ 0x43585400, "Conexant" },
112 	{ 0x44543000, "Diamond Technology" },
113 	{ 0x454d4300, "eMicro" },
114 	{ 0x45838300, "ESS Technology" },
115 	{ 0x48525300, "Intersil" },
116 	{ 0x49434500, "ICEnsemble" },
117 	{ 0x49544500, "ITE, Inc." },
118 	{ 0x4e534300, "National Semiconductor" },
119 	{ 0x50534300, "Philips Semiconductor" },
120 	{ 0x83847600, "SigmaTel" },
121 	{ 0x53494c00, "Silicon Laboratories" },
122 	{ 0x54524100, "TriTech" },
123 	{ 0x54584e00, "Texas Instruments" },
124 	{ 0x56494100, "VIA Technologies" },
125 	{ 0x57454300, "Winbond" },
126 	{ 0x574d4c00, "Wolfson" },
127 	{ 0x594d4800, "Yamaha" },
128 	{ 0x01408300, "SigmaTel" },
129 	{ 0x00000000, NULL }
130 };
131 
132 static void ad1886_patch(struct ac97_info *);
133 static void ad198x_patch(struct ac97_info *);
134 static void ad1981b_patch(struct ac97_info *);
135 static void cmi9739_patch(struct ac97_info *);
136 static void alc655_patch(struct ac97_info *);
137 
138 static struct ac97_codecid ac97codecid[] = {
139 	{ 0x41445303, 0x00, 0, "AD1819",	0 },
140 	{ 0x41445340, 0x00, 0, "AD1881",	0 },
141 	{ 0x41445348, 0x00, 0, "AD1881A",	0 },
142 	{ 0x41445360, 0x00, 0, "AD1885",	0 },
143 	{ 0x41445361, 0x00, 0, "AD1886", 	ad1886_patch },
144 	{ 0x41445362, 0x00, 0, "AD1887", 	0 },
145 	{ 0x41445363, 0x00, 0, "AD1886A", 	0 },
146 	{ 0x41445368, 0x00, 0, "AD1888", 	ad198x_patch },
147 	{ 0x41445370, 0x00, 0, "AD1980",	ad198x_patch },
148 	{ 0x41445372, 0x00, 0, "AD1981A",	0 },
149 	{ 0x41445374, 0x00, 0, "AD1981B",	ad1981b_patch },
150 	{ 0x41445375, 0x00, 0, "AD1985",	ad198x_patch },
151 	{ 0x41445378, 0x00, 0, "AD1986",	ad198x_patch },
152 	{ 0x414b4d00, 0x00, 1, "AK4540", 	0 },
153 	{ 0x414b4d01, 0x00, 1, "AK4542", 	0 },
154 	{ 0x414b4d02, 0x00, 1, "AK4543", 	0 },
155 	{ 0x414b4d06, 0x00, 0, "AK4544A",	0 },
156 	{ 0x454b4d07, 0x00, 0, "AK4545",	0 },
157 	{ 0x414c4320, 0x0f, 0, "ALC100",	0 },
158 	{ 0x414c4730, 0x0f, 0, "ALC101",	0 },
159 	{ 0x414c4710, 0x0f, 0, "ALC200", 	0 },
160 	{ 0x414c4740, 0x0f, 0, "ALC202", 	0 },
161 	{ 0x414c4720, 0x0f, 0, "ALC650", 	0 },
162 	{ 0x414c4752, 0x0f, 0, "ALC250",	0 },
163 	{ 0x414c4760, 0x0f, 0, "ALC655",	alc655_patch },
164 	{ 0x414c4770, 0x0f, 0, "ALC203",	0 },
165 	{ 0x414c4780, 0x0f, 0, "ALC658",	0 },
166 	{ 0x414c4790, 0x0f, 0, "ALC850",	0 },
167 	{ 0x43525900, 0x07, 0, "CS4297", 	0 },
168 	{ 0x43525910, 0x07, 0, "CS4297A", 	0 },
169 	{ 0x43525920, 0x07, 0, "CS4294/98",	0 },
170 	{ 0x4352592d, 0x07, 0, "CS4294",	0 },
171 	{ 0x43525930, 0x07, 0, "CS4299",	0 },
172 	{ 0x43525940, 0x07, 0, "CS4201",	0 },
173 	{ 0x43525958, 0x07, 0, "CS4205",	0 },
174 	{ 0x43525960, 0x07, 0, "CS4291A",	0 },
175 	{ 0x434d4961, 0x00, 0, "CMI9739",	cmi9739_patch },
176 	{ 0x434d4941, 0x00, 0, "CMI9738",	0 },
177 	{ 0x434d4978, 0x00, 0, "CMI9761",	0 },
178 	{ 0x434d4982, 0x00, 0, "CMI9761",	0 },
179 	{ 0x434d4983, 0x00, 0, "CMI9761",	0 },
180 	{ 0x43585421, 0x00, 0, "HSD11246",	0 },
181 	{ 0x43585428, 0x07, 0, "CX20468",	0 },
182 	{ 0x43585430, 0x00, 0, "CX20468-21",	0 },
183 	{ 0x44543000, 0x00, 0, "DT0398",	0 },
184 	{ 0x454d4323, 0x00, 0, "EM28023",	0 },
185 	{ 0x454d4328, 0x00, 0, "EM28028",	0 },
186 	{ 0x45838308, 0x00, 0, "ES1988",	0 }, /* Formerly ES1921(?) */
187 	{ 0x48525300, 0x00, 0, "HMP9701",	0 },
188 	{ 0x49434501, 0x00, 0, "ICE1230",	0 },
189 	{ 0x49434511, 0x00, 0, "ICE1232",	0 },
190 	{ 0x49434514, 0x00, 0, "ICE1232A",	0 },
191 	{ 0x49434551, 0x03, 0, "VT1616",	0 }, /* Via badged ICE */
192 	{ 0x49544520, 0x00, 0, "ITE2226E",	0 },
193 	{ 0x49544560, 0x07, 0, "ITE2646E",	0 }, /* XXX: patch needed */
194 	{ 0x4e534340, 0x00, 0, "LM4540",	0 }, /* Spec blank on revid */
195 	{ 0x4e534343, 0x00, 0, "LM4543",	0 }, /* Ditto */
196 	{ 0x4e534346, 0x00, 0, "LM4546A",	0 },
197 	{ 0x4e534348, 0x00, 0, "LM4548A",	0 },
198 	{ 0x4e534331, 0x00, 0, "LM4549",	0 },
199 	{ 0x4e534349, 0x00, 0, "LM4549A",	0 },
200 	{ 0x4e534350, 0x00, 0, "LM4550",	0 },
201 	{ 0x50534301, 0x00, 0, "UCB1510",	0 },
202 	{ 0x50534304, 0x00, 0, "UCB1400",	0 },
203 	{ 0x83847600, 0x00, 0, "STAC9700/83/84",	0 },
204 	{ 0x83847604, 0x00, 0, "STAC9701/03/04/05", 0 },
205 	{ 0x83847605, 0x00, 0, "STAC9704",	0 },
206 	{ 0x83847608, 0x00, 0, "STAC9708/11",	0 },
207 	{ 0x83847609, 0x00, 0, "STAC9721/23",	0 },
208 	{ 0x83847644, 0x00, 0, "STAC9744/45",	0 },
209 	{ 0x83847650, 0x00, 0, "STAC9750/51",	0 },
210 	{ 0x83847652, 0x00, 0, "STAC9752/53",	0 },
211 	{ 0x83847656, 0x00, 0, "STAC9756/57",	0 },
212 	{ 0x83847658, 0x00, 0, "STAC9758/59",	0 },
213 	{ 0x83847660, 0x00, 0, "STAC9760/61",	0 }, /* Extrapolated */
214 	{ 0x83847662, 0x00, 0, "STAC9762/63",	0 }, /* Extrapolated */
215 	{ 0x83847666, 0x00, 0, "STAC9766/67",	0 },
216 	{ 0x53494c22, 0x00, 0, "Si3036",	0 },
217 	{ 0x53494c23, 0x00, 0, "Si3038",	0 },
218 	{ 0x54524103, 0x00, 0, "TR28023",	0 }, /* Extrapolated */
219 	{ 0x54524106, 0x00, 0, "TR28026",	0 },
220 	{ 0x54524108, 0x00, 0, "TR28028",	0 },
221 	{ 0x54524123, 0x00, 0, "TR28602",	0 },
222 	{ 0x54524e03, 0x07, 0, "TLV320AIC27",	0 },
223 	{ 0x54584e20, 0x00, 0, "TLC320AD90",	0 },
224 	{ 0x56494161, 0x00, 0, "VIA1612A",      0 },
225 	{ 0x56494170, 0x00, 0, "VIA1617A",      0 },
226 	{ 0x574d4c00, 0x00, 0, "WM9701A",	0 },
227 	{ 0x574d4c03, 0x00, 0, "WM9703/4/7/8",	0 },
228 	{ 0x574d4c04, 0x00, 0, "WM9704Q",	0 },
229 	{ 0x574d4c05, 0x00, 0, "WM9705/10",	0 },
230 	{ 0x574d4d09, 0x00, 0, "WM9709",	0 },
231 	{ 0x574d4c12, 0x00, 0, "WM9711/12",	0 }, /* XXX: patch needed */
232 	{ 0x57454301, 0x00, 0, "W83971D",	0 },
233 	{ 0x594d4800, 0x00, 0, "YMF743",	0 },
234 	{ 0x594d4802, 0x00, 0, "YMF752",	0 },
235 	{ 0x594d4803, 0x00, 0, "YMF753",	0 },
236 	{ 0x01408384, 0x00, 0, "STAC9704",	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
ac97_rdcd(struct ac97_info * codec,int reg)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 		return i[!(j & 1)];
316 	}
317 	return AC97_READ(codec->methods, codec->devinfo, reg);
318 }
319 
320 void
ac97_wrcd(struct ac97_info * codec,int reg,u_int16_t val)321 ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val)
322 {
323 	AC97_WRITE(codec->methods, codec->devinfo, reg, val);
324 }
325 
326 static void
ac97_reset(struct ac97_info * codec)327 ac97_reset(struct ac97_info *codec)
328 {
329 	u_int32_t i, ps;
330 	ac97_wrcd(codec, AC97_REG_RESET, 0);
331 	for (i = 0; i < 500; i++) {
332 		ps = ac97_rdcd(codec, AC97_REG_POWER) & AC97_POWER_STATUS;
333 		if (ps == AC97_POWER_STATUS)
334 			return;
335 		DELAY(1000);
336 	}
337 	device_printf(codec->dev, "AC97 reset timed out.\n");
338 }
339 
340 int
ac97_setrate(struct ac97_info * codec,int which,int rate)341 ac97_setrate(struct ac97_info *codec, int which, int rate)
342 {
343 	u_int16_t v;
344 
345 	switch(which) {
346 	case AC97_REGEXT_FDACRATE:
347 	case AC97_REGEXT_SDACRATE:
348 	case AC97_REGEXT_LDACRATE:
349 	case AC97_REGEXT_LADCRATE:
350 	case AC97_REGEXT_MADCRATE:
351 		break;
352 
353 	default:
354 		return -1;
355 	}
356 
357 	mtx_lock(&codec->lock);
358 	if (rate != 0) {
359 		v = rate;
360 		if (codec->extstat & AC97_EXTCAP_DRA)
361 			v >>= 1;
362 		ac97_wrcd(codec, which, v);
363 	}
364 	v = ac97_rdcd(codec, which);
365 	if (codec->extstat & AC97_EXTCAP_DRA)
366 		v <<= 1;
367 	mtx_unlock(&codec->lock);
368 	return v;
369 }
370 
371 int
ac97_setextmode(struct ac97_info * codec,u_int16_t mode)372 ac97_setextmode(struct ac97_info *codec, u_int16_t mode)
373 {
374 	mode &= AC97_EXTCAPS;
375 	if ((mode & ~codec->extcaps) != 0) {
376 		device_printf(codec->dev, "ac97 invalid mode set 0x%04x\n",
377 			      mode);
378 		return -1;
379 	}
380 	mtx_lock(&codec->lock);
381 	ac97_wrcd(codec, AC97_REGEXT_STAT, mode);
382 	codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
383 	mtx_unlock(&codec->lock);
384 	return (mode == codec->extstat)? 0 : -1;
385 }
386 
387 u_int16_t
ac97_getextmode(struct ac97_info * codec)388 ac97_getextmode(struct ac97_info *codec)
389 {
390 	return codec->extstat;
391 }
392 
393 u_int16_t
ac97_getextcaps(struct ac97_info * codec)394 ac97_getextcaps(struct ac97_info *codec)
395 {
396 	return codec->extcaps;
397 }
398 
399 u_int16_t
ac97_getcaps(struct ac97_info * codec)400 ac97_getcaps(struct ac97_info *codec)
401 {
402 	return codec->caps;
403 }
404 
405 u_int32_t
ac97_getsubvendor(struct ac97_info * codec)406 ac97_getsubvendor(struct ac97_info *codec)
407 {
408 	return codec->subvendor;
409 }
410 
411 static int
ac97_setrecsrc(struct ac97_info * codec,int channel)412 ac97_setrecsrc(struct ac97_info *codec, int channel)
413 {
414 	struct ac97mixtable_entry *e = &codec->mix[channel];
415 
416 	if (e->recidx > 0) {
417 		int val = e->recidx - 1;
418 		val |= val << 8;
419 		mtx_lock(&codec->lock);
420 		ac97_wrcd(codec, AC97_REG_RECSEL, val);
421 		mtx_unlock(&codec->lock);
422 		return 0;
423 	} else
424 		return -1;
425 }
426 
427 static int
ac97_setmixer(struct ac97_info * codec,unsigned channel,unsigned left,unsigned right)428 ac97_setmixer(struct ac97_info *codec, unsigned channel, unsigned left, unsigned right)
429 {
430 	struct ac97mixtable_entry *e = &codec->mix[channel];
431 
432 	if (e->reg && e->enable && e->bits) {
433 		int mask, max, val, reg;
434 
435 		reg = (e->reg >= 0) ? e->reg : -e->reg;	/* AC97 register    */
436 		max = (1 << e->bits) - 1;		/* actual range	    */
437 		mask = (max << 8) | max;		/* bits of interest */
438 
439 		if (!e->stereo)
440 			right = left;
441 
442 		/*
443 		 * Invert the range if the polarity requires so,
444 		 * then scale to 0..max-1 to compute the value to
445 		 * write into the codec, and scale back to 0..100
446 		 * for the return value.
447 		 */
448 		if (e->reg > 0) {
449 			left = 100 - left;
450 			right = 100 - right;
451 		}
452 
453 		left = (left * max) / 100;
454 		right = (right * max) / 100;
455 
456 		val = (left << 8) | right;
457 
458 		left = (left * 100) / max;
459 		right = (right * 100) / max;
460 
461 		if (e->reg > 0) {
462 			left = 100 - left;
463 			right = 100 - right;
464 		}
465 
466 		/*
467 		 * For mono controls, trim val and mask, also taking
468 		 * care of e->ofs (offset of control field).
469 		 */
470 		if (e->ofs) {
471 			val &= max;
472 			val <<= e->ofs;
473 			mask = (max << e->ofs);
474 		}
475 
476 		/*
477 		 * If we have a mute bit, add it to the mask and
478 		 * update val and set mute if both channels require a
479 		 * zero volume.
480 		 */
481 		if (e->mute == 1) {
482 			mask |= AC97_MUTE;
483 			if (left == 0 && right == 0)
484 				val = AC97_MUTE;
485 		}
486 
487 		/*
488 		 * If the mask bit is set, do not alter the other bits.
489 		 */
490 		mtx_lock(&codec->lock);
491 		if (e->mask) {
492 			int cur = ac97_rdcd(codec, reg);
493 			val |= cur & ~(mask);
494 		}
495 		ac97_wrcd(codec, reg, val);
496 		mtx_unlock(&codec->lock);
497 		return left | (right << 8);
498 	} else {
499 		return -1;
500 	}
501 }
502 
503 static void
ac97_fix_auxout(struct ac97_info * codec)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
ac97_fix_tone(struct ac97_info * codec)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*
ac97_hw_desc(u_int32_t id,const char * vname,const char * cname,char * buf)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
ac97_initmixer(struct ac97_info * codec)586 ac97_initmixer(struct ac97_info *codec)
587 {
588 	ac97_patch codec_patch;
589 	const char *cname, *vname;
590 	char desc[80];
591 	device_t pdev;
592 	unsigned i, j, k, bit, old;
593 	u_int32_t id;
594 	int reg;
595 
596 	mtx_lock(&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 		mtx_unlock(&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 	k = ac97_rdcd(codec, AC97_REG_RESET);
611 	/*
612 	 * Let see if this codec can return consistent value.
613 	 * If not, turn on aggressive read workaround
614 	 * (STAC9704 comes in mind).
615 	 */
616 	if (i != j || j != k) {
617 		codec->flags |= AC97_F_RDCD_BUG;
618 		i = ac97_rdcd(codec, AC97_REG_RESET);
619 	}
620 	codec->caps = i & 0x03ff;
621 	codec->se =  (i & 0x7c00) >> 10;
622 
623 	id = (ac97_rdcd(codec, AC97_REG_ID1) << 16) | ac97_rdcd(codec, AC97_REG_ID2);
624 	if (id == 0 || id == 0xffffffff) {
625 		device_printf(codec->dev, "ac97 codec invalid or not present (id == %x)\n", id);
626 		mtx_unlock(&codec->lock);
627 		return ENODEV;
628 	}
629 
630 	pdev = codec->dev;
631 	while (strcmp(device_get_name(device_get_parent(pdev)), "pci") != 0) {
632 		/* find the top-level PCI device handler */
633 		pdev = device_get_parent(pdev);
634 	}
635 	codec->id = id;
636 	codec->subvendor = (u_int32_t)pci_get_subdevice(pdev) << 16;
637 	codec->subvendor |= (u_int32_t)pci_get_subvendor(pdev) &
638 	    0x0000ffff;
639 	codec->noext = 0;
640 	codec_patch = NULL;
641 
642 	cname = NULL;
643 	for (i = 0; ac97codecid[i].id; i++) {
644 		u_int32_t modelmask = 0xffffffff ^ ac97codecid[i].stepmask;
645 		if ((ac97codecid[i].id & modelmask) == (id & modelmask)) {
646 			codec->noext = ac97codecid[i].noext;
647 			codec_patch = ac97codecid[i].patch;
648 			cname = ac97codecid[i].name;
649 			break;
650 		}
651 	}
652 
653 	vname = NULL;
654 	for (i = 0; ac97vendorid[i].id; i++) {
655 		if (ac97vendorid[i].id == (id & 0xffffff00)) {
656 			vname = ac97vendorid[i].name;
657 			break;
658 		}
659 	}
660 
661 	codec->extcaps = 0;
662 	codec->extid = 0;
663 	codec->extstat = 0;
664 	if (!codec->noext) {
665 		i = ac97_rdcd(codec, AC97_REGEXT_ID);
666 		if (i != 0xffff) {
667 			codec->extcaps = i & 0x3fff;
668 			codec->extid =  (i & 0xc000) >> 14;
669 			codec->extstat = ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS;
670 		}
671 	}
672 
673 	for (i = 0; i < AC97_MIXER_SIZE; i++) {
674 		codec->mix[i] = ac97mixtable_default[i];
675 	}
676 	ac97_fix_auxout(codec);
677 	ac97_fix_tone(codec);
678 	if (codec_patch)
679 		codec_patch(codec);
680 
681 	for (i = 0; i < AC97_MIXER_SIZE; i++) {
682 		k = codec->noext? codec->mix[i].enable : 1;
683 		reg = codec->mix[i].reg;
684 		if (reg < 0)
685 			reg = -reg;
686 		if (k && reg) {
687 			j = old = ac97_rdcd(codec, reg);
688 			/*
689 			 * Test for mute bit (except for AC97_MIX_TONE,
690 			 * where we simply assume it as available).
691 			 */
692 			if (codec->mix[i].mute) {
693 				ac97_wrcd(codec, reg, j | 0x8000);
694 				j = ac97_rdcd(codec, reg);
695 			} else
696 				j |= 0x8000;
697 			if ((j & 0x8000)) {
698 				/*
699 				 * Test whether the control width should be
700 				 * 4, 5 or 6 bit. For 5bit register, we should
701 				 * test it whether it's really 5 or 6bit. Leave
702 				 * 4bit register alone, because sometimes an
703 				 * attempt to write past 4th bit may cause
704 				 * incorrect result especially for AC97_MIX_BEEP
705 				 * (ac97 2.3).
706 				 */
707 				bit = codec->mix[i].bits;
708 				if (bit == 5)
709 					bit++;
710 				j = ((1 << bit) - 1) << codec->mix[i].ofs;
711 				ac97_wrcd(codec, reg,
712 					j | (codec->mix[i].mute ? 0x8000 : 0));
713 				k = ac97_rdcd(codec, reg) & j;
714 				k >>= codec->mix[i].ofs;
715 				if (reg == AC97_MIX_TONE &&
716 							((k & 0x0001) == 0x0000))
717 					k >>= 1;
718 				for (j = 0; k >> j; j++)
719 					;
720 				if (j != 0) {
721 					codec->mix[i].enable = 1;
722 					codec->mix[i].bits = j;
723 				} else if (reg == AC97_MIX_BEEP) {
724 					/*
725 					 * Few codec such as CX20468-21 does
726 					 * have this control register, although
727 					 * the only usable part is the mute bit.
728 					 */
729 					codec->mix[i].enable = 1;
730 				} else
731 					codec->mix[i].enable = 0;
732 			} else
733 				codec->mix[i].enable = 0;
734 			ac97_wrcd(codec, reg, old);
735 		}
736 	}
737 
738 	device_printf(codec->dev, "<%s>\n",
739 		      ac97_hw_desc(codec->id, vname, cname, desc));
740 
741 	if (bootverbose) {
742 		if (codec->flags & AC97_F_RDCD_BUG)
743 			device_printf(codec->dev, "Buggy AC97 Codec: aggressive ac97_rdcd() workaround enabled\n");
744 		device_printf(codec->dev, "Codec features ");
745 		for (i = j = 0; i < 10; i++)
746 			if (codec->caps & (1 << i))
747 				printf("%s%s", j++? ", " : "", ac97feature[i]);
748 		printf("%s%d bit master volume", j++? ", " : "", codec->mix[SOUND_MIXER_VOLUME].bits);
749 		printf("%s%s\n", j? ", " : "", ac97enhancement[codec->se]);
750 
751 		if (codec->extcaps != 0 || codec->extid) {
752 			device_printf(codec->dev, "%s codec",
753 				      codec->extid? "Secondary" : "Primary");
754 			if (codec->extcaps)
755 				printf(" extended features ");
756 			for (i = j = 0; i < 14; i++)
757 				if (codec->extcaps & (1 << i))
758 					printf("%s%s", j++? ", " : "", ac97extfeature[i]);
759 			printf("\n");
760 		}
761 	}
762 
763 	i = 0;
764 	while ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0) {
765 		if (++i == 100) {
766 			device_printf(codec->dev, "ac97 codec reports dac not ready\n");
767 			break;
768 		}
769 		DELAY(1000);
770 	}
771 	if (bootverbose)
772 		device_printf(codec->dev, "ac97 codec dac ready count: %d\n", i);
773 	mtx_unlock(&codec->lock);
774 	return 0;
775 }
776 
777 static unsigned
ac97_reinitmixer(struct ac97_info * codec)778 ac97_reinitmixer(struct ac97_info *codec)
779 {
780 	mtx_lock(&codec->lock);
781 	codec->count = AC97_INIT(codec->methods, codec->devinfo);
782 	if (codec->count == 0) {
783 		device_printf(codec->dev, "ac97 codec init failed\n");
784 		mtx_unlock(&codec->lock);
785 		return ENODEV;
786 	}
787 
788 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
789 	ac97_reset(codec);
790 	ac97_wrcd(codec, AC97_REG_POWER, (codec->flags & AC97_F_EAPD_INV)? 0x8000 : 0x0000);
791 
792 	if (!codec->noext) {
793 		ac97_wrcd(codec, AC97_REGEXT_STAT, codec->extstat);
794 		if ((ac97_rdcd(codec, AC97_REGEXT_STAT) & AC97_EXTCAPS)
795 		    != codec->extstat)
796 			device_printf(codec->dev, "ac97 codec failed to reset extended mode (%x, got %x)\n",
797 				      codec->extstat,
798 				      ac97_rdcd(codec, AC97_REGEXT_STAT) &
799 				      AC97_EXTCAPS);
800 	}
801 
802 	if ((ac97_rdcd(codec, AC97_REG_POWER) & 2) == 0)
803 		device_printf(codec->dev, "ac97 codec reports dac not ready\n");
804 	mtx_unlock(&codec->lock);
805 	return 0;
806 }
807 
808 struct ac97_info *
ac97_create(device_t dev,void * devinfo,kobj_class_t cls)809 ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
810 {
811 	struct ac97_info *codec;
812 	int i;
813 
814 	codec = malloc(sizeof(*codec), M_AC97, M_WAITOK | M_ZERO);
815 	snprintf(codec->name, sizeof(codec->name), "%s:ac97",
816 	    device_get_nameunit(dev));
817 	mtx_init(&codec->lock, codec->name, "ac97 codec", MTX_DEF);
818 	codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO);
819 	codec->dev = dev;
820 	codec->devinfo = devinfo;
821 	codec->flags = 0;
822 
823 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
824 	    "eapdinv", &i) == 0 && i != 0)
825 		codec->flags |= AC97_F_EAPD_INV;
826 
827 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
828 	    "softpcmvol", &i) == 0 && i != 0)
829 		pcm_setflags(dev, pcm_getflags(dev) | SD_F_SOFTPCMVOL);
830 
831 	return codec;
832 }
833 
834 void
ac97_destroy(struct ac97_info * codec)835 ac97_destroy(struct ac97_info *codec)
836 {
837 	mtx_lock(&codec->lock);
838 	if (codec->methods != NULL)
839 		kobj_delete(codec->methods, M_AC97);
840 	mtx_destroy(&codec->lock);
841 	free(codec, M_AC97);
842 }
843 
844 void
ac97_setflags(struct ac97_info * codec,u_int32_t val)845 ac97_setflags(struct ac97_info *codec, u_int32_t val)
846 {
847 	codec->flags = val;
848 }
849 
850 u_int32_t
ac97_getflags(struct ac97_info * codec)851 ac97_getflags(struct ac97_info *codec)
852 {
853 	return codec->flags;
854 }
855 
856 static void
ad1886_patch(struct ac97_info * codec)857 ad1886_patch(struct ac97_info *codec)
858 {
859 #define AC97_AD_JACK_SPDIF 0x72
860 	/*
861 	 *    Presario700 workaround
862 	 *     for Jack Sense/SPDIF Register misetting causing
863 	 *    no audible output
864 	 *    by Santiago Nullo 04/05/2002
865 	 */
866 	ac97_wrcd(codec, AC97_AD_JACK_SPDIF, 0x0010);
867 }
868 
869 static void
ad198x_patch(struct ac97_info * codec)870 ad198x_patch(struct ac97_info *codec)
871 {
872 	switch (ac97_getsubvendor(codec)) {
873 	case 0x11931043:	/* Not for ASUS A9T (probably else too). */
874 		break;
875 	default:
876 		ac97_wrcd(codec, 0x76, ac97_rdcd(codec, 0x76) | 0x0420);
877 		break;
878 	}
879 }
880 
881 static void
ad1981b_patch(struct ac97_info * codec)882 ad1981b_patch(struct ac97_info *codec)
883 {
884 	/*
885 	 * Enable headphone jack sensing.
886 	 */
887 	switch (ac97_getsubvendor(codec)) {
888 	case 0x02d91014:	/* IBM Thinkcentre */
889 	case 0x099c103c:	/* HP nx6110 */
890 		ac97_wrcd(codec, AC97_AD_JACK_SPDIF,
891 		    ac97_rdcd(codec, AC97_AD_JACK_SPDIF) | 0x0800);
892 		break;
893 	default:
894 		break;
895 	}
896 }
897 
898 static void
cmi9739_patch(struct ac97_info * codec)899 cmi9739_patch(struct ac97_info *codec)
900 {
901 	/*
902 	 * Few laptops need extra register initialization
903 	 * to power up the internal speakers.
904 	 */
905 	switch (ac97_getsubvendor(codec)) {
906 	case 0x18431043:	/* ASUS W1000N */
907 		ac97_wrcd(codec, AC97_REG_POWER, 0x000f);
908 		ac97_wrcd(codec, AC97_MIXEXT_CLFE, 0x0000);
909 		ac97_wrcd(codec, 0x64, 0x7110);
910 		break;
911 	default:
912 		break;
913 	}
914 }
915 
916 static void
alc655_patch(struct ac97_info * codec)917 alc655_patch(struct ac97_info *codec)
918 {
919 	/*
920 	 * MSI (Micro-Star International) specific EAPD quirk.
921 	 */
922 	switch (ac97_getsubvendor(codec)) {
923 	case 0x00611462:	/* MSI S250 */
924 	case 0x01311462:	/* MSI S270 */
925 	case 0x01611462:	/* LG K1 Express */
926 	case 0x03511462:	/* MSI L725 */
927 		ac97_wrcd(codec, 0x7a, ac97_rdcd(codec, 0x7a) & 0xfffd);
928 		break;
929 	case 0x10ca1734:
930 		/*
931 		 * Amilo Pro V2055 with ALC655 has phone out by default
932 		 * disabled (surround on), leaving us only with internal
933 		 * speakers. This should really go to mixer. We write the
934 		 * Data Flow Control reg.
935 		 */
936 		ac97_wrcd(codec, 0x6a, ac97_rdcd(codec, 0x6a) | 0x0001);
937 		break;
938 	default:
939 		break;
940 	}
941 }
942 
943 /* -------------------------------------------------------------------- */
944 
945 static int
sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)946 sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)
947 {
948 	struct ac97_info *codec;
949 	int ea, inv, err = 0;
950 	u_int16_t val;
951 
952 	codec = oidp->oid_arg1;
953 	if (codec == NULL || codec->id == 0)
954 		return EINVAL;
955 	mtx_lock(&codec->lock);
956 	val = ac97_rdcd(codec, AC97_REG_POWER);
957 	inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1;
958 	ea = (val >> 15) ^ inv;
959 	mtx_unlock(&codec->lock);
960 	err = sysctl_handle_int(oidp, &ea, 0, req);
961 	if (err == 0 && req->newptr != NULL) {
962 		if (ea != 0 && ea != 1)
963 			return EINVAL;
964 		if (ea != ((val >> 15) ^ inv)) {
965 			mtx_lock(&codec->lock);
966 			ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000);
967 			mtx_unlock(&codec->lock);
968 		}
969 	}
970 	return err;
971 }
972 
973 static void
ac97_init_sysctl(struct ac97_info * codec)974 ac97_init_sysctl(struct ac97_info *codec)
975 {
976 	u_int16_t orig, val;
977 
978 	if (codec == NULL || codec->dev == NULL)
979 		return;
980 	mtx_lock(&codec->lock);
981 	orig = ac97_rdcd(codec, AC97_REG_POWER);
982 	ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000);
983 	val = ac97_rdcd(codec, AC97_REG_POWER);
984 	ac97_wrcd(codec, AC97_REG_POWER, orig);
985 	mtx_unlock(&codec->lock);
986 	if ((val & 0x8000) == (orig & 0x8000))
987 		return;
988 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev),
989 	    SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)),
990             OID_AUTO, "eapd",
991 	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
992 	    codec, sizeof(codec), sysctl_hw_snd_ac97_eapd,
993 	    "I", "AC97 External Amplifier");
994 }
995 
996 static int
ac97mix_init(struct snd_mixer * m)997 ac97mix_init(struct snd_mixer *m)
998 {
999 	struct ac97_info *codec = mix_getdevinfo(m);
1000 	u_int32_t i, mask;
1001 
1002 	if (codec == NULL)
1003 		return -1;
1004 
1005 	if (ac97_initmixer(codec))
1006 		return -1;
1007 
1008 	switch (codec->id) {
1009 	case 0x41445374:	/* AD1981B */
1010 		switch (codec->subvendor) {
1011 		case 0x02d91014:
1012 			/*
1013 			 * IBM Thinkcentre:
1014 			 *
1015 			 * Tie "ogain" and "phout" to "vol" since its
1016 			 * master volume is basically useless and can't
1017 			 * control anything.
1018 			 */
1019 			mask = 0;
1020 			if (codec->mix[SOUND_MIXER_OGAIN].enable)
1021 				mask |= SOUND_MASK_OGAIN;
1022 			if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
1023 				mask |= SOUND_MASK_PHONEOUT;
1024 			if (codec->mix[SOUND_MIXER_VOLUME].enable)
1025 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
1026 				    mask);
1027 			else {
1028 				mix_setparentchild(m, SOUND_MIXER_VOLUME,
1029 				    mask);
1030 				mix_setrealdev(m, SOUND_MIXER_VOLUME,
1031 				    SOUND_MIXER_NONE);
1032 			}
1033 			break;
1034 		case 0x099c103c:
1035 			/*
1036 			 * HP nx6110:
1037 			 *
1038 			 * By default, "vol" is controlling internal speakers
1039 			 * (not a master volume!) and "ogain" is controlling
1040 			 * headphone. Enable dummy "phout" so it can be
1041 			 * remapped to internal speakers and virtualize
1042 			 * "vol" to control both.
1043 			 */
1044 			codec->mix[SOUND_MIXER_OGAIN].enable = 1;
1045 			codec->mix[SOUND_MIXER_PHONEOUT].enable = 1;
1046 			mix_setrealdev(m, SOUND_MIXER_PHONEOUT,
1047 			    SOUND_MIXER_VOLUME);
1048 			mix_setrealdev(m, SOUND_MIXER_VOLUME,
1049 			    SOUND_MIXER_NONE);
1050 			mix_setparentchild(m, SOUND_MIXER_VOLUME,
1051 			    SOUND_MASK_OGAIN | SOUND_MASK_PHONEOUT);
1052 			break;
1053 		default:
1054 			break;
1055 		}
1056 		break;
1057 	case 0x434d4941:	/* CMI9738 */
1058 	case 0x434d4961:	/* CMI9739 */
1059 	case 0x434d4978:	/* CMI9761 */
1060 	case 0x434d4982:	/* CMI9761 */
1061 	case 0x434d4983:	/* CMI9761 */
1062 		bzero(&codec->mix[SOUND_MIXER_PCM],
1063 		    sizeof(codec->mix[SOUND_MIXER_PCM]));
1064 		pcm_setflags(codec->dev, pcm_getflags(codec->dev) |
1065 		    SD_F_SOFTPCMVOL);
1066 		/* XXX How about master volume ? */
1067 		break;
1068 	default:
1069 		break;
1070 	}
1071 
1072 	if (pcm_getflags(codec->dev) & SD_F_SOFTPCMVOL)
1073 		ac97_wrcd(codec, AC97_MIX_PCM, 0);
1074 
1075 	mask = 0;
1076 	for (i = 0; i < AC97_MIXER_SIZE; i++)
1077 		mask |= codec->mix[i].enable? 1 << i : 0;
1078 	mix_setdevs(m, mask);
1079 
1080 	mask = 0;
1081 	for (i = 0; i < AC97_MIXER_SIZE; i++)
1082 		mask |= codec->mix[i].recidx? 1 << i : 0;
1083 	mix_setrecdevs(m, mask);
1084 
1085 	ac97_init_sysctl(codec);
1086 
1087 	return 0;
1088 }
1089 
1090 static int
ac97mix_uninit(struct snd_mixer * m)1091 ac97mix_uninit(struct snd_mixer *m)
1092 {
1093 	struct ac97_info *codec = mix_getdevinfo(m);
1094 
1095 	if (codec == NULL)
1096 		return -1;
1097 	ac97_destroy(codec);
1098 	return 0;
1099 }
1100 
1101 static int
ac97mix_reinit(struct snd_mixer * m)1102 ac97mix_reinit(struct snd_mixer *m)
1103 {
1104 	struct ac97_info *codec = mix_getdevinfo(m);
1105 
1106 	if (codec == NULL)
1107 		return -1;
1108 	return ac97_reinitmixer(codec);
1109 }
1110 
1111 static int
ac97mix_set(struct snd_mixer * m,unsigned dev,unsigned left,unsigned right)1112 ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1113 {
1114 	struct ac97_info *codec = mix_getdevinfo(m);
1115 
1116 	if (codec == NULL || dev >= AC97_MIXER_SIZE)
1117 		return -1;
1118 	return ac97_setmixer(codec, dev, left, right);
1119 }
1120 
1121 static u_int32_t
ac97mix_setrecsrc(struct snd_mixer * m,u_int32_t src)1122 ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1123 {
1124 	int i;
1125 	struct ac97_info *codec = mix_getdevinfo(m);
1126 
1127 	if (codec == NULL)
1128 		return -1;
1129 	for (i = 0; i < AC97_MIXER_SIZE; i++)
1130 		if ((src & (1 << i)) != 0)
1131 			break;
1132 	return (ac97_setrecsrc(codec, i) == 0)? 1U << i : 0xffffffffU;
1133 }
1134 
1135 static kobj_method_t ac97mixer_methods[] = {
1136     	KOBJMETHOD(mixer_init,		ac97mix_init),
1137     	KOBJMETHOD(mixer_uninit,	ac97mix_uninit),
1138     	KOBJMETHOD(mixer_reinit,	ac97mix_reinit),
1139     	KOBJMETHOD(mixer_set,		ac97mix_set),
1140     	KOBJMETHOD(mixer_setrecsrc,	ac97mix_setrecsrc),
1141 	KOBJMETHOD_END
1142 };
1143 MIXER_DECLARE(ac97mixer);
1144 
1145 /* -------------------------------------------------------------------- */
1146 
1147 kobj_class_t
ac97_getmixerclass(void)1148 ac97_getmixerclass(void)
1149 {
1150 	return &ac97mixer_class;
1151 }
1152