ac97.c revision 170342
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
35SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/ac97.c 170342 2007-06-05 20:30:16Z ariff $");
36
37MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
38
39struct 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
53struct 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
66struct ac97_vendorid {
67	u_int32_t   id;
68	const char *name;
69};
70
71struct 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
79static 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
99static 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
132static 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
239static 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
274static 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
287static 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
304u_int16_t
305ac97_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
325void
326ac97_wrcd(struct ac97_info *codec, int reg, u_int16_t val)
327{
328	AC97_WRITE(codec->methods, codec->devinfo, reg, val);
329}
330
331static void
332ac97_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
345int
346ac97_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
376int
377ac97_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
392u_int16_t
393ac97_getextmode(struct ac97_info *codec)
394{
395	return codec->extstat;
396}
397
398u_int16_t
399ac97_getextcaps(struct ac97_info *codec)
400{
401	return codec->extcaps;
402}
403
404u_int16_t
405ac97_getcaps(struct ac97_info *codec)
406{
407	return codec->caps;
408}
409
410u_int32_t
411ac97_getsubvendor(struct ac97_info *codec)
412{
413	return codec->subvendor;
414}
415
416static int
417ac97_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
432static int
433ac97_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
511static void
512ac97_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
546static void
547ac97_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
575static const char*
576ac97_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
593static unsigned
594ac97_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
790static unsigned
791ac97_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
821struct ac97_info *
822ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
823{
824	struct ac97_info *codec;
825	int eapdinv;
826
827	codec = (struct ac97_info *)malloc(sizeof *codec, M_AC97, M_NOWAIT | M_ZERO);
828	if (codec == NULL)
829		return NULL;
830
831	snprintf(codec->name, sizeof(codec->name), "%s:ac97",
832	    device_get_nameunit(dev));
833	codec->lock = snd_mtxcreate(codec->name, "ac97 codec");
834	codec->methods = kobj_create(cls, M_AC97, M_WAITOK | M_ZERO);
835	codec->dev = dev;
836	codec->devinfo = devinfo;
837	codec->flags = 0;
838	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
839		    "eapdinv", &eapdinv) == 0) {
840		if (eapdinv != 0)
841			codec->flags |= AC97_F_EAPD_INV;
842	}
843	return codec;
844}
845
846void
847ac97_destroy(struct ac97_info *codec)
848{
849	snd_mtxlock(codec->lock);
850	if (codec->methods != NULL)
851		kobj_delete(codec->methods, M_AC97);
852	snd_mtxfree(codec->lock);
853	free(codec, M_AC97);
854}
855
856void
857ac97_setflags(struct ac97_info *codec, u_int32_t val)
858{
859	codec->flags = val;
860}
861
862u_int32_t
863ac97_getflags(struct ac97_info *codec)
864{
865	return codec->flags;
866}
867
868/* -------------------------------------------------------------------- */
869
870#ifdef SND_DYNSYSCTL
871static int
872sysctl_hw_snd_ac97_eapd(SYSCTL_HANDLER_ARGS)
873{
874	struct ac97_info *codec;
875	int ea, inv, err = 0;
876	u_int16_t val;
877
878	codec = oidp->oid_arg1;
879	if (codec == NULL || codec->id == 0 || codec->lock == NULL)
880		return EINVAL;
881	snd_mtxlock(codec->lock);
882	val = ac97_rdcd(codec, AC97_REG_POWER);
883	inv = (codec->flags & AC97_F_EAPD_INV) ? 0 : 1;
884	ea = (val >> 15) ^ inv;
885	snd_mtxunlock(codec->lock);
886	err = sysctl_handle_int(oidp, &ea, 0, req);
887	if (err == 0 && req->newptr != NULL) {
888		if (ea != 0 && ea != 1)
889			return EINVAL;
890		if (ea != ((val >> 15) ^ inv)) {
891			snd_mtxlock(codec->lock);
892			ac97_wrcd(codec, AC97_REG_POWER, val ^ 0x8000);
893			snd_mtxunlock(codec->lock);
894		}
895	}
896	return err;
897}
898#endif
899
900static void
901ac97_init_sysctl(struct ac97_info *codec)
902{
903#ifdef SND_DYNSYSCTL
904	u_int16_t orig, val;
905
906	if (codec == NULL || codec->dev == NULL)
907		return;
908	snd_mtxlock(codec->lock);
909	orig = ac97_rdcd(codec, AC97_REG_POWER);
910	ac97_wrcd(codec, AC97_REG_POWER, orig ^ 0x8000);
911	val = ac97_rdcd(codec, AC97_REG_POWER);
912	ac97_wrcd(codec, AC97_REG_POWER, orig);
913	snd_mtxunlock(codec->lock);
914	if ((val & 0x8000) == (orig & 0x8000))
915		return;
916	SYSCTL_ADD_PROC(device_get_sysctl_ctx(codec->dev),
917	    SYSCTL_CHILDREN(device_get_sysctl_tree(codec->dev)),
918            OID_AUTO, "eapd", CTLTYPE_INT | CTLFLAG_RW,
919	    codec, sizeof(codec), sysctl_hw_snd_ac97_eapd,
920	    "I", "AC97 External Amplifier");
921#endif
922}
923
924static int
925ac97mix_init(struct snd_mixer *m)
926{
927	struct ac97_info *codec = mix_getdevinfo(m);
928	u_int32_t i, mask;
929
930	if (codec == NULL)
931		return -1;
932
933	if (ac97_initmixer(codec))
934		return -1;
935
936	switch (codec->id) {
937	case 0x41445374:	/* AD1981B */
938		if (codec->subvendor == 0x02d91014) {
939			/*
940			 * IBM Thinkcentre:
941			 * Tie "ogain" and "phone" to "vol" since its
942			 * master volume is basically useless and can't
943			 * control anything.
944			 */
945			mask = 0;
946			if (codec->mix[SOUND_MIXER_OGAIN].enable)
947				mask |= SOUND_MASK_OGAIN;
948			if (codec->mix[SOUND_MIXER_PHONEOUT].enable)
949				mask |= SOUND_MASK_PHONEOUT;
950			if (codec->mix[SOUND_MIXER_VOLUME].enable)
951				mix_setparentchild(m, SOUND_MIXER_VOLUME,
952				    mask);
953			else {
954				mix_setparentchild(m, SOUND_MIXER_VOLUME,
955				    mask);
956				mix_setrealdev(m, SOUND_MIXER_VOLUME,
957				    SOUND_MIXER_NONE);
958			}
959		}
960		break;
961	case 0x434d4941:	/* CMI9738 */
962	case 0x434d4961:	/* CMI9739 */
963	case 0x434d4978:	/* CMI9761 */
964	case 0x434d4982:	/* CMI9761 */
965	case 0x434d4983:	/* CMI9761 */
966		ac97_wrcd(codec, AC97_MIX_PCM, 0);
967		bzero(&codec->mix[SOUND_MIXER_PCM],
968		    sizeof(codec->mix[SOUND_MIXER_PCM]));
969		pcm_setflags(codec->dev, pcm_getflags(codec->dev) |
970		    SD_F_SOFTPCMVOL);
971		/* XXX How about master volume ? */
972		break;
973	default:
974		break;
975	}
976
977#if 0
978	/* XXX For the sake of debugging purposes */
979	mix_setparentchild(m, SOUND_MIXER_VOLUME,
980	    SOUND_MASK_PCM | SOUND_MASK_CD);
981	mix_setrealdev(m, SOUND_MIXER_VOLUME, SOUND_MIXER_NONE);
982	ac97_wrcd(codec, AC97_MIX_MASTER, 0);
983#endif
984
985	mask = 0;
986	for (i = 0; i < AC97_MIXER_SIZE; i++)
987		mask |= codec->mix[i].enable? 1 << i : 0;
988	mix_setdevs(m, mask);
989
990	mask = 0;
991	for (i = 0; i < AC97_MIXER_SIZE; i++)
992		mask |= codec->mix[i].recidx? 1 << i : 0;
993	mix_setrecdevs(m, mask);
994
995	ac97_init_sysctl(codec);
996
997	return 0;
998}
999
1000static int
1001ac97mix_uninit(struct snd_mixer *m)
1002{
1003	struct ac97_info *codec = mix_getdevinfo(m);
1004
1005	if (codec == NULL)
1006		return -1;
1007	/*
1008	if (ac97_uninitmixer(codec))
1009		return -1;
1010	*/
1011	ac97_destroy(codec);
1012	return 0;
1013}
1014
1015static int
1016ac97mix_reinit(struct snd_mixer *m)
1017{
1018	struct ac97_info *codec = mix_getdevinfo(m);
1019
1020	if (codec == NULL)
1021		return -1;
1022	return ac97_reinitmixer(codec);
1023}
1024
1025static int
1026ac97mix_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1027{
1028	struct ac97_info *codec = mix_getdevinfo(m);
1029
1030	if (codec == NULL || dev >= AC97_MIXER_SIZE)
1031		return -1;
1032	return ac97_setmixer(codec, dev, left, right);
1033}
1034
1035static int
1036ac97mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
1037{
1038	int i;
1039	struct ac97_info *codec = mix_getdevinfo(m);
1040
1041	if (codec == NULL)
1042		return -1;
1043	for (i = 0; i < AC97_MIXER_SIZE; i++)
1044		if ((src & (1 << i)) != 0)
1045			break;
1046	return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
1047}
1048
1049static kobj_method_t ac97mixer_methods[] = {
1050    	KOBJMETHOD(mixer_init,		ac97mix_init),
1051    	KOBJMETHOD(mixer_uninit,	ac97mix_uninit),
1052    	KOBJMETHOD(mixer_reinit,	ac97mix_reinit),
1053    	KOBJMETHOD(mixer_set,		ac97mix_set),
1054    	KOBJMETHOD(mixer_setrecsrc,	ac97mix_setrecsrc),
1055	{ 0, 0 }
1056};
1057MIXER_DECLARE(ac97mixer);
1058
1059/* -------------------------------------------------------------------- */
1060
1061kobj_class_t
1062ac97_getmixerclass(void)
1063{
1064	return &ac97mixer_class;
1065}
1066