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