1/*
2 * AC97 interface
3 *
4 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
5 * Copyright (c) 2008-2013, J��r��me Duval
6 *
7 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without modification,
9 * are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 *   this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 *   this list of conditions and the following disclaimer in the documentation
15 *   and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30
31#include <KernelExport.h>
32#include <OS.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <MediaDefs.h>
37#include "ac97.h"
38
39#define LOG(x)	dprintf x
40
41#define B_UTF8_REGISTERED	"\xC2\xAE"
42
43bool ac97_reg_is_valid(ac97_dev *dev, uint8 reg);
44void ac97_amp_enable(ac97_dev *dev, bool onoff);
45void ac97_dump_capabilities(ac97_dev *dev);
46void ac97_detect_capabilities(ac97_dev *dev);
47void ac97_detect_rates(ac97_dev *dev);
48void ac97_update_register_cache(ac97_dev *dev);
49
50
51const char * stereo_enhancement_technique[] =
52{
53	"No 3D Stereo Enhancement",
54	"Analog Devices",
55	"Creative Technology",
56	"National Semiconductor",
57	"Yamaha",
58	"BBE Sound",
59	"Crystal Semiconductor",
60	"Qsound Labs",
61	"Spatializer Audio Laboratories",
62	"SRS Labs",
63	"Platform Tech",
64	"AKM Semiconductor",
65	"Aureal",
66	"Aztech Labs",
67	"Binaura",
68	"ESS Technology",
69	"Harman International",
70	"Nvidea",
71	"Philips",
72	"Texas Instruments",
73	"VLSI Technology",
74	"TriTech",
75	"Realtek",
76	"Samsung",
77	"Wolfson Microelectronics",
78	"Delta Integration",
79	"SigmaTel",
80	"KS Waves",
81	"Rockwell",
82	"Unknown (29)",
83	"Unknown (30)",
84	"Unknown (31)"
85};
86
87
88static void default_init(ac97_dev *dev);
89static void ad1819_init(ac97_dev *dev);
90static void ad1881_init(ac97_dev *dev);
91static void ad1885_init(ac97_dev *dev);
92static void ad1886_init(ac97_dev *dev);
93static void ad1980_init(ac97_dev *dev);
94static void ad1981b_init(ac97_dev *dev);
95static void alc203_init(ac97_dev *dev);
96static void alc650_init(ac97_dev *dev);
97static void alc655_init(ac97_dev *dev);
98static void alc850_init(ac97_dev *dev);
99static void stac9708_init(ac97_dev *dev);
100static void stac9721_init(ac97_dev *dev);
101static void stac9744_init(ac97_dev *dev);
102static void stac9756_init(ac97_dev *dev);
103static void stac9758_init(ac97_dev *dev);
104static void tr28028_init(ac97_dev *dev);
105static void wm9701_init(ac97_dev *dev);
106static void wm9703_init(ac97_dev *dev);
107static void wm9704_init(ac97_dev *dev);
108
109bool ad1819_set_rate(ac97_dev *dev, uint8 reg, uint32 rate);
110bool ad1819_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate);
111
112
113typedef struct
114{
115	uint32 id;
116	uint32 mask;
117	codec_init init;
118	const char *info;
119} codec_table;
120
121
122codec_table codecs[] =
123{
124	{ CODEC_ID_AD1819,	0xffffffff, ad1819_init,	"Analog Devices AD1819A, AD1819B SoundPort" B_UTF8_REGISTERED },
125	{ CODEC_ID_AD1881,	0xffffffff, ad1881_init,	"Analog Devices AD1881 SoundMAX" B_UTF8_REGISTERED },
126	{ CODEC_ID_AD1881A,	0xffffffff, ad1881_init,	"Analog Devices AD1881A SoundMAX" B_UTF8_REGISTERED },
127	{ CODEC_ID_AD1885,	0xffffffff, ad1885_init,	"Analog Devices AD1885 SoundMAX" B_UTF8_REGISTERED },
128	{ CODEC_ID_AD1886,	0xffffffff, ad1886_init,	"Analog Devices AD1886 SoundMAX" B_UTF8_REGISTERED },
129	{ CODEC_ID_AD1886A,	0xffffffff, ad1881_init,	"Analog Devices AD1886A SoundMAX" B_UTF8_REGISTERED },
130	{ CODEC_ID_AD1887,	0xffffffff, ad1881_init,	"Analog Devices AD1887 SoundMAX" B_UTF8_REGISTERED },
131	{ CODEC_ID_AD1888,	0xffffffff, ad1881_init,	"Analog Devices AD1888 SoundMAX" B_UTF8_REGISTERED },
132	{ CODEC_ID_AD1980,	0xffffffff, ad1980_init,	"Analog Devices AD1980 SoundMAX" B_UTF8_REGISTERED },
133	{ 0x41445371,		0xffffffff, default_init,	"Analog Devices 0x41445371 (\?\?\?)" },
134	{ 0x41445372,		0xffffffff, default_init,	"Analog Devices AD1981A SoundMAX" B_UTF8_REGISTERED },
135	{ CODEC_ID_AD1981B,	0xffffffff, ad1981b_init,	"Analog Devices AD1981B SoundMAX" B_UTF8_REGISTERED },
136	{ CODEC_ID_AD1985,	0xffffffff, default_init,	"Analog Devices AD1985 SoundMAX" B_UTF8_REGISTERED },
137	{ CODEC_ID_AD1986,	0xffffffff, default_init,	"Analog Devices AD1986 SoundMAX" B_UTF8_REGISTERED },
138	{ CODEC_ID_AK4540,	0xffffffff, default_init,	"Asahi Kasei AK4540" },
139	{ CODEC_ID_AK4542,	0xffffffff, default_init,	"Asahi Kasei AK4542" },
140	{ CODEC_ID_AK4543,	0xffffffff, default_init,	"Asahi Kasei AK4543" },
141	{ 0x414b4d06,		0xffffffff, default_init,	"Asahi Kasei AK4544A" },
142	{ 0x414b4d07,		0xffffffff, default_init,	"Asahi Kasei AK4545" },
143	{ 0x414c4300, 		0xffffff00, default_init,	"Avance Logic (Realtek) ALC100" }, /* 0x4300 = ALC100 */
144	{ 0x414c4320,		0xfffffff0, default_init,	"Avance Logic (Realtek) ALC100/ALC100P, RL5383/RL5522" },
145	{ CODEC_ID_ALC201A, 0xfffffff0, default_init,	"Avance Logic (Realtek) ALC200/ALC200A, ALC201/ALC201A" }, /* 0x4710 = ALC201A */
146	{ 0x414c4720,		0xffffffff, alc650_init,	"Avance Logic (Realtek) ALC650" }, /* 0x4720 = ALC650 */
147	{ 0x414c4730, 		0xffffffff, default_init,	"Avance Logic (Realtek) ALC101" },
148	{ 0x414c4740,		0xfffffff0, default_init,	"Avance Logic (Realtek) ALC202/ALC202A" },
149	{ 0x414c4750,		0xfffffff0, default_init,	"Avance Logic (Realtek) ALC250" },
150	{ 0x414c4760,		0xfffffff0, alc655_init,	"Avance Logic (Realtek) ALC655" }, /* 0x4760 = ALC655 */
151	{ 0x414c4770,		0xfffffff0, alc203_init,	"Avance Logic (Realtek) ALC203" },
152	{ 0x414c4780,		0xffffffff, alc655_init,	"Avance Logic (Realtek) ALC658" },
153	{ 0x414c4790,		0xfffffff0, alc850_init,	"Avance Logic (Realtek) ALC850" },
154	{ 0x434d4941,		0xffffffff, default_init,	"C-Media CMI9738" },
155	{ 0x434d4961,		0xffffffff, default_init,	"C-Media CMI9739" },
156	{ 0x43525900,		0xffffffff, default_init,	"Cirrus Logic CS4297" },
157	{ 0x43525903,		0xffffffff, default_init,	"Cirrus Logic CS4297" },
158	{ 0x43525913,		0xffffffff, default_init,	"Cirrus Logic CS4297A" },
159	{ 0x43525914,		0xffffffff, default_init,	"Cirrus Logic CS4297B" },
160	{ 0x43525923,		0xffffffff, default_init,	"Cirrus Logic CS4294C" },
161	{ 0x4352592b,		0xffffffff, default_init,	"Cirrus Logic CS4298C" },
162	{ CODEC_ID_CS4299A,	0xffffffff, default_init,	"Cirrus Logic CS4299A" },
163	{ CODEC_ID_CS4299C,	0xffffffff, default_init,	"Cirrus Logic CS4299C" },
164	{ CODEC_ID_CS4299D,	0xffffffff, default_init,	"Cirrus Logic CS4299D" },
165	{ 0x43525941,		0xffffffff, default_init,	"Cirrus Logic CS4201A" },
166	{ 0x43525951,		0xffffffff, default_init,	"Cirrus Logic CS4205A" },
167	{ 0x43525961,		0xffffffff, default_init,	"Cirrus Logic CS4291A" },
168	{ 0x43585421,		0xffffffff, default_init,	"HSD11246" },
169	{ 0x44543031,		0xffffffff, default_init,	"DT0398" },
170	{ 0x454d4328,		0xffffffff, default_init,	"EM28028" },
171	{ 0x45838308,		0xffffffff, default_init,	"ESS Technology ES1921" },
172	{ 0x49434501,		0xffffffff, default_init,	"ICEnsemble ICE1230" },
173	{ 0x49434511,		0xffffffff, default_init,	"ICEnsemble ICE1232" },
174	{ 0x49434514,		0xffffffff, default_init,	"ICEnsemble ICE1232A" },
175	{ 0x49434551,		0xffffffff, default_init,	"Via Technologies VT1616" }, /* rebranded from ICEnsemble */
176	{ 0x49544520,		0xffffffff, default_init,	"Integrated Technology Express ITE2226E" },
177	{ 0x49544560,		0xffffffff, default_init,	"Integrated Technology Express ITE2646E" },
178	{ 0x4e534331,		0xffffffff, default_init,	"National Semiconductor LM4549" },
179	{ CODEC_ID_STAC9700,0xffffffff, default_init,	"SigmaTel STAC9700/9783/9784" },
180	{ CODEC_ID_STAC9704,0xffffffff, default_init,	"SigmaTel STAC9701/03, STAC9704/07, STAC9705 (\?\?\?)" },
181	{ CODEC_ID_STAC9705,0xffffffff, default_init,	"SigmaTel STAC9704 (\?\?\?)" },
182	{ CODEC_ID_STAC9708,0xffffffff, stac9708_init,	"SigmaTel STAC9708/9711" },
183	{ CODEC_ID_STAC9721,0xffffffff, stac9721_init,	"SigmaTel STAC9721/9723" },
184	{ CODEC_ID_STAC9744,0xffffffff, stac9744_init,	"SigmaTel STAC9744" },
185	{ CODEC_ID_STAC9750,0xffffffff, default_init,	"SigmaTel STAC9750/51" },
186	{ CODEC_ID_STAC9752,0xffffffff, default_init,	"SigmaTel STAC9752/53" },
187	{ CODEC_ID_STAC9756,0xffffffff, stac9756_init,	"SigmaTel STAC9756/9757" },
188	{ CODEC_ID_STAC9758,0xffffffff, stac9758_init,	"SigmaTel STAC9758/59" },
189	{ CODEC_ID_STAC9766,0xffffffff, default_init,	"SigmaTel STAC9766/67" },
190	{ 0x53494c22,		0xffffffff, default_init,	"Silicon Laboratory Si3036" },
191	{ 0x53494c23,		0xffffffff, default_init,	"Silicon Laboratory Si3038" },
192	{ 0x53544d02,		0xffffffff, default_init,	"ST7597" },
193	{ 0x54524103,		0xffffffff, default_init,	"TriTech TR28023" },
194	{ 0x54524106,		0xffffffff, default_init,	"TriTech TR28026" },
195	{ 0x54524108,		0xffffffff, tr28028_init,	"TriTech TR28028" },
196	{ 0x54524123,		0xffffffff, default_init,	"TriTech TR28602" },
197	{ 0x56494161,		0xffffffff, default_init,	"Via Technologies VIA1612A" },
198	{ 0x56494170,		0xffffffff, default_init,	"Via Technologies VIA1617A" },
199	{ 0x574d4c00,		0xffffffff, wm9701_init,	"Wolfson WM9701A" },
200	{ 0x574d4c03,		0xffffffff, wm9703_init,	"Wolfson WM9703/9704" },
201	{ 0x574d4c04,		0xffffffff, wm9704_init,	"Wolfson WM9704 (quad)" },
202	{ 0x574d4c05,		0xffffffff, wm9703_init,	"Wolfson WM9705/WM9710" },
203	{ 0x574d4d09,		0xffffffff, default_init,	"Wolfson WM9709" },
204	{ 0x574d4c12,		0xffffffff, default_init,	"Wolfson WM9711/12" },
205	{ 0x574d4c13,		0xffffffff, default_init,	"Wolfson WM9713/14" },
206	{ 0x57454301,		0xffffffff, default_init,	"Wolfson W83971D" },
207	/* Vendors only: */
208	{ 0x41445300,		0xffffff00, default_init,	"Analog Devices" },
209	{ 0x414b4d00,		0xffffff00, default_init,	"Asahi Kasei" },
210	{ 0x414c4700,		0xffffff00, default_init,	"Avance Logic (Realtek)" },
211	{ 0x434d4900,		0xffffff00, default_init,	"C-Media" },
212	{ 0x43525900,		0xffffff00, default_init,	"Cirrus Logic" },
213	{ 0x45838300,		0xffffff00, default_init,	"ESS Technology" },
214	{ 0x49434500,		0xffffff00, default_init,	"ICEnsemble" },
215	{ 0x49544500,		0xffffff00, default_init,	"ITE, Inc." },
216	{ 0x4e534300,		0xffffff00, default_init,	"National Semiconductor" },
217	{ 0x83847600,		0xffffff00, default_init,	"SigmaTel" },
218	{ 0x53494c00,		0xffffff00, default_init,	"Silicon Laboratory" },
219	{ 0x54524100,		0xffffff00, default_init,	"TriTech" },
220	{ 0x54584e00,		0xffffff00, default_init,	"Texas Instruments" },
221	{ 0x56494100,		0xffffff00, default_init,	"VIA Technologies" },
222	{ 0x574d4c00,		0xffffff00, default_init,	"Wolfson" },
223	{ 0x594d4800,		0xffffff00, default_init,	"Yamaha" },
224	{ 0x00000000,		0x00000000, default_init,	"Unknown" } /* must be last one, matches every codec */
225};
226
227
228static codec_table *
229find_codec_table(uint32 codecid)
230{
231	codec_table *codec;
232	for (codec = codecs; codec->id; codec++)
233		if ((codec->id & codec->mask) == (codecid & codec->mask))
234			break;
235	return codec;
236}
237
238
239void
240ac97_attach(ac97_dev **_dev, codec_reg_read reg_read, codec_reg_write reg_write, void *cookie,
241	ushort subvendor_id, ushort subsystem_id)
242{
243	ac97_dev *dev;
244	codec_table *codec;
245	int i;
246
247	*_dev = dev = (ac97_dev *) malloc(sizeof(ac97_dev));
248	memset(dev->reg_cache, 0, sizeof(dev->reg_cache));
249	dev->cookie = cookie;
250	dev->reg_read = reg_read;
251	dev->reg_write = reg_write;
252	dev->set_rate = 0;
253	dev->get_rate = 0;
254	dev->clock = 48000; /* default clock on non-broken motherboards */
255	dev->min_vsr = 0x0001;
256	dev->max_vsr = 0xffff;
257	dev->reversed_eamp_polarity = false;
258	dev->capabilities = 0;
259
260	dev->subsystem = (subvendor_id << 16) | subsystem_id;
261
262	if (dev->subsystem == 0x161f202f
263		|| dev->subsystem == 0x161f203a
264		|| dev->subsystem == 0x161f203e
265		|| dev->subsystem == 0x161f204c
266		|| dev->subsystem == 0x104d8144
267		|| dev->subsystem == 0x104d8197
268		|| dev->subsystem == 0x104d81c0
269		|| dev->subsystem == 0x104d81c5
270		|| dev->subsystem == 0x103c3089
271		|| dev->subsystem == 0x103c309a
272		|| dev->subsystem == 0x10338213
273		|| dev->subsystem == 0x103382be) {
274		dev->reversed_eamp_polarity = true;
275	}
276
277	/* reset the codec */
278	LOG(("codec reset\n"));
279	ac97_reg_uncached_write(dev, AC97_RESET, 0x0000);
280	for (i = 0; i < 500; i++) {
281		if ((ac97_reg_uncached_read(dev, AC97_POWERDOWN) & 0xf) == 0xf)
282			break;
283		snooze(1000);
284	}
285
286	dev->codec_id = ((uint32)reg_read(cookie, AC97_VENDOR_ID1) << 16) | reg_read(cookie, AC97_VENDOR_ID2);
287	codec = find_codec_table(dev->codec_id);
288	dev->codec_info = codec->info;
289	dev->init = codec->init;
290
291	dev->codec_3d_stereo_enhancement = stereo_enhancement_technique[(ac97_reg_cached_read(dev, AC97_RESET) >> 10) & 31];
292
293	/* setup register cache */
294	ac97_update_register_cache(dev);
295
296	ac97_reg_update_bits(dev, AC97_EXTENDED_STAT_CTRL, 1, 1); // enable variable rate audio
297
298	ac97_detect_capabilities(dev);
299
300	dev->init(dev);
301	ac97_amp_enable(dev, true);
302
303	/* set mixer defaults, enabled Line-out sources are PCM-out, CD-in, Line-in */
304	ac97_reg_update(dev, AC97_CENTER_LFE_VOLUME, 0x0000);	/* set LFE & center volume 0dB */
305	ac97_reg_update(dev, AC97_SURR_VOLUME, 0x0000);			/* set surround volume 0dB */
306	ac97_reg_update(dev, AC97_MASTER_VOLUME, 0x0000);		/* set master output 0dB */
307	ac97_reg_update(dev, AC97_AUX_OUT_VOLUME, 0x0000);		/* set aux output 0dB */
308	ac97_reg_update(dev, AC97_MONO_VOLUME, 0x0000);			/* set mono output 0dB */
309	ac97_reg_update(dev, AC97_PCM_OUT_VOLUME, 0x0808);		/* enable pcm-out */
310	ac97_reg_update(dev, AC97_CD_VOLUME, 0x0808);			/* enable cd-in */
311	ac97_reg_update(dev, AC97_LINE_IN_VOLUME, 0x0808);		/* enable line-in */
312
313	/* set record line in */
314	ac97_reg_update(dev, AC97_RECORD_SELECT, 0x0404);
315
316	LOG(("codec vendor id      = %#08" B_PRIx32 "\n", dev->codec_id));
317	LOG(("codec description     = %s\n", dev->codec_info));
318	LOG(("codec 3d enhancement = %s\n", dev->codec_3d_stereo_enhancement));
319
320	ac97_dump_capabilities(dev);
321}
322
323
324void
325ac97_detach(ac97_dev *dev)
326{
327	/* Mute everything */
328	ac97_reg_update_bits(dev, AC97_CENTER_LFE_VOLUME, 0x8000, 0x8000);
329	ac97_reg_update_bits(dev, AC97_SURR_VOLUME, 0x8000, 0x8000);
330	ac97_reg_update_bits(dev, AC97_MASTER_VOLUME, 0x8000, 0x8000);
331	ac97_reg_update_bits(dev, AC97_AUX_OUT_VOLUME, 0x8000, 0x8000);
332	ac97_reg_update_bits(dev, AC97_MONO_VOLUME, 0x8000, 0x8000);
333	ac97_reg_update_bits(dev, AC97_PCM_OUT_VOLUME, 0x8000, 0x8000);
334	ac97_reg_update_bits(dev, AC97_CD_VOLUME, 0x8000, 0x8000);
335	ac97_reg_update_bits(dev, AC97_LINE_IN_VOLUME, 0x8000, 0x8000);
336
337	ac97_amp_enable(dev, false);
338
339	free(dev);
340}
341
342
343void
344ac97_suspend(ac97_dev *dev)
345{
346	ac97_amp_enable(dev, false);
347}
348
349
350void
351ac97_resume(ac97_dev *dev)
352{
353	ac97_amp_enable(dev, true);
354}
355
356
357void
358ac97_reg_cached_write(ac97_dev *dev, uint8 reg, uint16 value)
359{
360	if (!ac97_reg_is_valid(dev, reg))
361		return;
362	dev->reg_write(dev->cookie, reg, value);
363	dev->reg_cache[reg] = value;
364}
365
366
367uint16
368ac97_reg_cached_read(ac97_dev *dev, uint8 reg)
369{
370	if (!ac97_reg_is_valid(dev, reg))
371		return 0;
372	return dev->reg_cache[reg];
373}
374
375void
376ac97_reg_uncached_write(ac97_dev *dev, uint8 reg, uint16 value)
377{
378	if (!ac97_reg_is_valid(dev, reg))
379		return;
380	dev->reg_write(dev->cookie, reg, value);
381}
382
383
384uint16
385ac97_reg_uncached_read(ac97_dev *dev, uint8 reg)
386{
387	if (!ac97_reg_is_valid(dev, reg))
388		return 0;
389	return dev->reg_read(dev->cookie, reg);
390}
391
392
393bool
394ac97_reg_update(ac97_dev *dev, uint8 reg, uint16 value)
395{
396	if (!ac97_reg_is_valid(dev, reg))
397		return false;
398	if (ac97_reg_cached_read(dev, reg) == value)
399		return false;
400	ac97_reg_cached_write(dev, reg, value);
401	return true;
402}
403
404
405bool
406ac97_reg_update_bits(ac97_dev *dev, uint8 reg, uint16 mask, uint16 value)
407{
408	uint16 old;
409	if (!ac97_reg_is_valid(dev, reg))
410		return false;
411	old = ac97_reg_cached_read(dev, reg);
412	value &= mask;
413	value |= (old & ~mask);
414	if (old == value)
415		return false;
416	ac97_reg_cached_write(dev, reg, value);
417	return true;
418}
419
420
421void
422ac97_update_register_cache(ac97_dev *dev)
423{
424	int reg;
425	for (reg = 0; reg <= 0x7e; reg += 2)
426		dev->reg_cache[reg] = ac97_reg_uncached_read(dev, reg);
427}
428
429
430bool
431ac97_set_rate(ac97_dev *dev, uint8 reg, uint32 rate)
432{
433	uint32 value;
434	uint32 old;
435
436	if (dev->set_rate)
437		return dev->set_rate(dev, reg, rate);
438
439	value = (uint32)((rate * 48000ULL) / dev->clock); /* need 64 bit calculation for rates 96000 or higher */
440
441	LOG(("ac97_set_rate: clock = %" B_PRIu32 ", "
442		"rate = %" B_PRIu32 ", "
443		"value = %" B_PRIu32 "\n",
444		dev->clock, rate, value));
445
446	/* if double rate audio is currently enabled, divide value by 2 */
447	if (ac97_reg_cached_read(dev, AC97_EXTENDED_STAT_CTRL) & 0x0002)
448		value /= 2;
449
450	if (value < dev->min_vsr || value > dev->max_vsr)
451		return false;
452
453	old = ac97_reg_cached_read(dev, reg);
454	ac97_reg_cached_write(dev, reg, value);
455	if (value != ac97_reg_uncached_read(dev, reg)) {
456		LOG(("ac97_set_rate failed, new rate %d\n", ac97_reg_uncached_read(dev, reg)));
457		ac97_reg_cached_write(dev, reg, old);
458		return false;
459	}
460	LOG(("ac97_set_rate done\n"));
461	return true;
462}
463
464
465bool
466ac97_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate)
467{
468	uint32 value;
469
470	if (dev->get_rate)
471		return dev->get_rate(dev, reg, rate);
472
473	value = ac97_reg_cached_read(dev, reg);
474	if (value == 0)
475		return false;
476
477	/* if double rate audio is currently enabled, multiply value by 2 */
478	if (ac97_reg_cached_read(dev, AC97_EXTENDED_STAT_CTRL) & 0x0002)
479		value *= 2;
480
481	*rate = (uint32)((value * (uint64)dev->clock) / 48000); /* need 64 bit calculation to avoid overflow*/
482	return true;
483}
484
485
486void
487ac97_set_clock(ac97_dev *dev, uint32 clock)
488{
489	LOG(("ac97_set_clock: clock = %" B_PRIu32 "\n", clock));
490	dev->clock = clock;
491	ac97_detect_rates(dev);
492	ac97_dump_capabilities(dev);
493}
494
495
496void
497ac97_detect_capabilities(ac97_dev *dev)
498{
499	uint16 val;
500
501	val = ac97_reg_cached_read(dev, AC97_RESET);
502	if (val & 0x0001)
503		dev->capabilities |= CAP_PCM_MIC;
504	if (val & 0x0004)
505		dev->capabilities |= CAP_BASS_TREBLE_CTRL;
506	if (val & 0x0008)
507		dev->capabilities |= CAP_SIMULATED_STEREO;
508	if (val & 0x0010)
509		dev->capabilities |= CAP_HEADPHONE_OUT;
510	if (val & 0x0020)
511		dev->capabilities |= CAP_LAUDNESS;
512	if (val & 0x0040)
513		dev->capabilities |= CAP_DAC_18BIT;
514	if (val & 0x0080)
515		dev->capabilities |= CAP_DAC_20BIT;
516	if (val & 0x0100)
517		dev->capabilities |= CAP_ADC_18BIT;
518	if (val & 0x0200)
519		dev->capabilities |= CAP_ADC_20BIT;
520	if (val & 0x7C00)
521		dev->capabilities |= CAP_3D_ENHANCEMENT;
522
523	val = ac97_reg_cached_read(dev, AC97_EXTENDED_ID);
524	if (val & EXID_VRA)
525		dev->capabilities |= CAP_VARIABLE_PCM;
526	if (val & EXID_DRA)
527		dev->capabilities |= CAP_DOUBLE_PCM;
528	if (val & EXID_SPDIF)
529		dev->capabilities |= CAP_SPDIF;
530	if (val & EXID_VRM)
531		dev->capabilities |= CAP_VARIABLE_MIC;
532	if (val & EXID_CDAC)
533		dev->capabilities |= CAP_CENTER_DAC;
534	if (val & EXID_SDAC)
535		dev->capabilities |= CAP_SURR_DAC;
536	if (val & EXID_LDAC)
537		dev->capabilities |= CAP_LFE_DAC;
538	if (val & EXID_AMAP)
539		dev->capabilities |= CAP_AMAP;
540	if ((val & (EXID_REV0 | EXID_REV1)) == 0)
541		dev->capabilities |= CAP_REV21;
542	if ((val & (EXID_REV0 | EXID_REV1)) == EXID_REV0)
543		dev->capabilities |= CAP_REV22;
544	if ((val & (EXID_REV0 | EXID_REV1)) == EXID_REV1)
545		dev->capabilities |= CAP_REV23;
546
547	ac97_detect_rates(dev);
548}
549
550void
551ac97_detect_rates(ac97_dev *dev)
552{
553	uint32 oldrate;
554
555	dev->capabilities &= ~CAP_PCM_RATE_MASK;
556
557	if (!ac97_get_rate(dev, AC97_PCM_FRONT_DAC_RATE, &oldrate))
558		oldrate = 48000;
559
560	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 20000))
561		dev->capabilities |= CAP_PCM_RATE_CONTINUOUS;
562	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 8000))
563		dev->capabilities |= CAP_PCM_RATE_8000;
564	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 11025))
565		dev->capabilities |= CAP_PCM_RATE_11025;
566	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 12000))
567		dev->capabilities |= CAP_PCM_RATE_12000;
568	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 16000))
569		dev->capabilities |= CAP_PCM_RATE_16000;
570	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 22050))
571		dev->capabilities |= CAP_PCM_RATE_22050;
572	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 24000))
573		dev->capabilities |= CAP_PCM_RATE_24000;
574	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 32000))
575		dev->capabilities |= CAP_PCM_RATE_32000;
576	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 44100))
577		dev->capabilities |= CAP_PCM_RATE_44100;
578	if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 48000))
579		dev->capabilities |= CAP_PCM_RATE_48000;
580
581	if (dev->capabilities & CAP_DOUBLE_PCM) {
582		// enable double rate mode
583		if (ac97_reg_update_bits(dev, AC97_EXTENDED_STAT_CTRL, 0x0002, 0x0002)) {
584			if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 88200))
585				dev->capabilities |= CAP_PCM_RATE_88200;
586			if (ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 96000))
587				dev->capabilities |= CAP_PCM_RATE_96000;
588			// disable double rate mode
589			ac97_reg_update_bits(dev, AC97_EXTENDED_STAT_CTRL, 0x0002, 0x0000);
590		}
591	}
592
593	ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, oldrate);
594}
595
596
597void
598ac97_dump_capabilities(ac97_dev *dev)
599{
600	LOG(("AC97 capabilities:\n"));
601	if (ac97_has_capability(dev, CAP_PCM_MIC))
602		LOG(("CAP_PCM_MIC\n"));
603	if (ac97_has_capability(dev, CAP_BASS_TREBLE_CTRL))
604		LOG(("CAP_BASS_TREBLE_CTRL\n"));
605	if (ac97_has_capability(dev, CAP_SIMULATED_STEREO))
606		LOG(("CAP_SIMULATED_STEREO\n"));
607	if (ac97_has_capability(dev, CAP_HEADPHONE_OUT))
608		LOG(("CAP_HEADPHONE_OUT\n"));
609	if (ac97_has_capability(dev, CAP_LAUDNESS))
610		LOG(("CAP_LAUDNESS\n"));
611	if (ac97_has_capability(dev, CAP_DAC_18BIT))
612		LOG(("CAP_DAC_18BIT\n"));
613	if (ac97_has_capability(dev, CAP_DAC_20BIT))
614		LOG(("CAP_DAC_20BIT\n"));
615	if (ac97_has_capability(dev, CAP_ADC_18BIT))
616		LOG(("CAP_ADC_18BIT\n"));
617	if (ac97_has_capability(dev, CAP_ADC_20BIT))
618		LOG(("CAP_ADC_20BIT\n"));
619	if (ac97_has_capability(dev, CAP_3D_ENHANCEMENT))
620		LOG(("CAP_3D_ENHANCEMENT\n"));
621	if (ac97_has_capability(dev, CAP_VARIABLE_PCM))
622		LOG(("CAP_VARIABLE_PCM\n"));
623	if (ac97_has_capability(dev, CAP_DOUBLE_PCM))
624		LOG(("CAP_DOUBLE_PCM\n"));
625	if (ac97_has_capability(dev, CAP_VARIABLE_MIC))
626		LOG(("CAP_VARIABLE_MIC\n"));
627	if (ac97_has_capability(dev, CAP_CENTER_DAC))
628		LOG(("CAP_CENTER_DAC\n"));
629	if (ac97_has_capability(dev, CAP_SURR_DAC))
630		LOG(("CAP_SURR_DAC\n"));
631	if (ac97_has_capability(dev, CAP_LFE_DAC))
632		LOG(("CAP_LFE_DAC\n"));
633	if (ac97_has_capability(dev, CAP_AMAP))
634		LOG(("CAP_AMAP\n"));
635	if (ac97_has_capability(dev, CAP_REV21))
636		LOG(("CAP_REV21\n"));
637	if (ac97_has_capability(dev, CAP_REV22))
638		LOG(("CAP_REV22\n"));
639	if (ac97_has_capability(dev, CAP_REV23))
640		LOG(("CAP_REV23\n"));
641	if (ac97_has_capability(dev, CAP_PCM_RATE_CONTINUOUS))
642		LOG(("CAP_PCM_RATE_CONTINUOUS\n"));
643	if (ac97_has_capability(dev, CAP_PCM_RATE_8000))
644		LOG(("CAP_PCM_RATE_8000\n"));
645	if (ac97_has_capability(dev, CAP_PCM_RATE_11025))
646		LOG(("CAP_PCM_RATE_11025\n"));
647	if (ac97_has_capability(dev, CAP_PCM_RATE_12000))
648		LOG(("CAP_PCM_RATE_12000\n"));
649	if (ac97_has_capability(dev, CAP_PCM_RATE_16000))
650		LOG(("CAP_PCM_RATE_16000\n"));
651	if (ac97_has_capability(dev, CAP_PCM_RATE_22050))
652		LOG(("CAP_PCM_RATE_22050\n"));
653	if (ac97_has_capability(dev, CAP_PCM_RATE_24000))
654		LOG(("CAP_PCM_RATE_24000\n"));
655	if (ac97_has_capability(dev, CAP_PCM_RATE_32000))
656		LOG(("CAP_PCM_RATE_32000\n"));
657	if (ac97_has_capability(dev, CAP_PCM_RATE_44100))
658		LOG(("CAP_PCM_RATE_44100\n"));
659	if (ac97_has_capability(dev, CAP_PCM_RATE_48000))
660		LOG(("CAP_PCM_RATE_48000\n"));
661	if (ac97_has_capability(dev, CAP_PCM_RATE_88200))
662		LOG(("CAP_PCM_RATE_88200\n"));
663	if (ac97_has_capability(dev, CAP_PCM_RATE_96000))
664		LOG(("CAP_PCM_RATE_96000\n"));
665}
666
667
668bool
669ac97_has_capability(ac97_dev *dev, uint64 cap)
670{
671	// return (dev->capabilities & cap); // does not work because of 64 bit to integer trucation
672	return (dev->capabilities & cap) != 0;
673}
674
675/*************************************************
676 * Codec specific initialization, etc.
677 */
678
679bool
680ac97_reg_is_valid(ac97_dev *dev, uint8 reg)
681{
682	if (reg & 1)
683		return false;
684	if (reg > 0x7e)
685		return false;
686
687	switch (dev->codec_id) {
688		case CODEC_ID_AK4540:
689		case CODEC_ID_AK4542:
690			if (reg < 0x1e || reg == 0x20 || reg == 0x26 || reg > 0x7a)
691				return true;
692			return false;
693
694		case CODEC_ID_AD1819:
695		case CODEC_ID_AD1881:
696		case CODEC_ID_AD1881A:
697			if (reg < 0x3a || reg > 0x6e)
698				return true;
699			return false;
700
701		case CODEC_ID_AD1885:
702		case CODEC_ID_AD1886:
703		case CODEC_ID_AD1886A:
704		case CODEC_ID_AD1887:
705			if (reg < 0x3c || reg == 0x5a || reg > 0x6e)
706				return true;
707			return false;
708
709		case CODEC_ID_STAC9700:
710		case CODEC_ID_STAC9704:
711		case CODEC_ID_STAC9705:
712		case CODEC_ID_STAC9708:
713		case CODEC_ID_STAC9721:
714		case CODEC_ID_STAC9744:
715		case CODEC_ID_STAC9756:
716			if (reg < 0x3c || reg > 0x58)
717				return true;
718			return false;
719
720		default:
721			return true;
722	}
723}
724
725
726void
727ac97_amp_enable(ac97_dev *dev, bool yesno)
728{
729	switch (dev->codec_id) {
730		case CODEC_ID_CS4299A:
731		case CODEC_ID_CS4299C:
732		case CODEC_ID_CS4299D:
733			LOG(("cs4299_amp_enable\n"));
734			if (yesno)
735				ac97_reg_cached_write(dev, 0x68, 0x8004);
736			else
737				ac97_reg_cached_write(dev, 0x68, 0);
738			break;
739
740		default:
741			LOG(("ac97_amp_enable, reverse eamp = %d\n", dev->reversed_eamp_polarity));
742			LOG(("powerdown register was = %#04x\n", ac97_reg_uncached_read(dev, AC97_POWERDOWN)));
743			if (dev->reversed_eamp_polarity)
744				yesno = !yesno;
745			if (yesno)
746				ac97_reg_cached_write(dev, AC97_POWERDOWN, ac97_reg_uncached_read(dev, AC97_POWERDOWN) & ~0x8000); /* switch on (low active) */
747			else
748				ac97_reg_cached_write(dev, AC97_POWERDOWN, ac97_reg_uncached_read(dev, AC97_POWERDOWN) | 0x8000); /* switch off */
749			LOG(("powerdown register is = %#04x\n", ac97_reg_uncached_read(dev, AC97_POWERDOWN)));
750		break;
751	}
752}
753
754
755bool
756ad1819_set_rate(ac97_dev *dev, uint8 reg, uint32 rate)
757{
758	uint32 value;
759
760	value = (uint32)((rate * 48000ULL) / dev->clock); /* need 64 bit calculation for rates 96000 or higher */
761
762	LOG(("ad1819_set_rate: clock = %" B_PRIu32 ", "
763		"rate = %" B_PRIu32 ", "
764		"value = %" B_PRIu32 "\n",
765		dev->clock, rate, value));
766
767	if (value < 0x1B58 || value > 0xBB80)
768		return false;
769
770	switch (reg) {
771		case AC97_PCM_FRONT_DAC_RATE:
772			ac97_reg_cached_write(dev, AC97_AD_SAMPLE_RATE_0, value);
773			return true;
774
775		case AC97_PCM_L_R_ADC_RATE:
776			ac97_reg_cached_write(dev, AC97_AD_SAMPLE_RATE_1, value);
777			return true;
778
779		default:
780			return false;
781	}
782}
783
784
785bool
786ad1819_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate)
787{
788	uint32 value;
789
790	switch (reg) {
791		case AC97_PCM_FRONT_DAC_RATE:
792			value = ac97_reg_cached_read(dev, AC97_AD_SAMPLE_RATE_0);
793			break;
794
795		case AC97_PCM_L_R_ADC_RATE:
796			value = ac97_reg_cached_read(dev, AC97_AD_SAMPLE_RATE_1);
797			break;
798
799		default:
800			return false;
801	}
802
803	*rate = (uint32)((value * (uint64)dev->clock) / 48000); /* need 64 bit calculation to avoid overflow*/
804	return true;
805}
806
807
808void
809default_init(ac97_dev *dev)
810{
811	LOG(("default_init\n"));
812}
813
814
815void
816ad1819_init(ac97_dev *dev)
817{
818	LOG(("ad1819_init\n"));
819
820	/* Default config for system with single AD1819 codec */
821	ac97_reg_cached_write(dev, AC97_AD_SERIAL_CONFIG, 0x7000);
822	ac97_update_register_cache(dev);
823
824	/* The AD1819 chip has proprietary  sample rate controls
825	 * Setup sample rate 0 generator for DAC,
826	 * Setup sample rate 1 generator for ADC,
827	 * ARSR=1, DRSR=0, ALSR=1, DLSR=0
828	 */
829	ac97_reg_cached_write(dev, AC97_AD_MISC_CONTROL, 0x0101);
830	/* connect special rate set/get functions */
831	dev->set_rate = ad1819_set_rate;
832	dev->get_rate = ad1819_get_rate;
833	ac97_detect_rates(dev);
834	ac97_set_rate(dev, AC97_PCM_FRONT_DAC_RATE, 48000);
835	ac97_set_rate(dev, AC97_PCM_L_R_ADC_RATE, 48000);
836}
837
838
839void
840ad1881_init(ac97_dev *dev)
841{
842	LOG(("ad1881_init\n"));
843
844	/* Default config for system with single AD1819 codec,
845	 * BROKEN on systems with master & slave codecs */
846	ac97_reg_cached_write(dev, AC97_AD_SERIAL_CONFIG, 0x7000);
847	ac97_update_register_cache(dev);
848
849	/* Setup DAC and ADC rate generator assignments compatible with AC97 */
850	ac97_reg_cached_write(dev, AC97_AD_MISC_CONTROL, 0x0404);
851
852	/* Setup variable frame rate limits */
853	dev->min_vsr = 0x1B58;	/*  7kHz */
854	dev->max_vsr = 0xBB80;	/* 48kHz */
855}
856
857
858void
859ad1885_init(ac97_dev *dev)
860{
861	LOG(("ad1885_init\n"));
862	ad1881_init(dev);
863
864	/* disable jack sense 0 and 1 (JS0, JS1) to turn off automatic mute */
865	ac97_reg_cached_write(dev, AC97_AD_JACK_SENSE, ac97_reg_cached_read(dev, AC97_AD_JACK_SENSE) | 0x0300);
866}
867
868
869void
870ad1886_init(ac97_dev *dev)
871{
872	LOG(("ad1886_init\n"));
873	ad1881_init(dev);
874
875	/* change jack sense to always activate outputs*/
876	ac97_reg_cached_write(dev, AC97_AD_JACK_SENSE, 0x0010);
877	/* change SPDIF to a valid value */
878	ac97_reg_cached_write(dev, AC97_SPDIF_CONTROL, 0x2a20);
879}
880
881
882void
883ad1980_init(ac97_dev *dev)
884{
885	LOG(("ad1980_init\n"));
886
887	/* Select only master codec,
888	 * SPDIF and DAC are linked
889	 */
890	ac97_reg_cached_write(dev, AC97_AD_SERIAL_CONFIG, 0x1001);
891	ac97_update_register_cache(dev);
892
893	/* Select Line-out driven with mixer data (not surround data)
894	 * Select Headphone-out driven with mixer data (not surround data),
895	 * LOSEL = 0, HPSEL = 1
896	 * XXX this one needs to be changed to support surround	out
897	 */
898	ac97_reg_cached_write(dev, AC97_AD_MISC_CONTROL, 0x0400);
899}
900
901
902void
903ad1981b_init(ac97_dev *dev)
904{
905	LOG(("ad1981b_init\n"));
906	if (dev->subsystem == 0x0e11005a
907		|| dev->subsystem == 0x103c006d
908		|| dev->subsystem == 0x103c088c
909		|| dev->subsystem == 0x103c0890
910		|| dev->subsystem == 0x103c0934
911		|| dev->subsystem == 0x103c0938
912		|| dev->subsystem == 0x103c0944
913		|| dev->subsystem == 0x103c099c
914		|| dev->subsystem == 0x101402d9) {
915		ac97_reg_cached_write(dev, AC97_AD_JACK_SENSE,
916				ac97_reg_cached_read(dev, AC97_AD_JACK_SENSE) | 0x0800);
917	}
918}
919
920
921void
922alc203_init(ac97_dev *dev)
923{
924	LOG(("alc203_init\n"));
925
926	ac97_reg_update_bits(dev, AC97_ALC650_CLOCK_SOURCE, 0x400, 0x400);
927}
928
929
930void
931alc650_init(ac97_dev *dev)
932{
933	LOG(("alc650_init\n"));
934
935	/* Enable Surround, LFE and Center downmix into Line-out,
936	 * Set Surround-out as duplicated Line-out.
937	 */
938	ac97_reg_cached_write(dev, AC97_ALC650_MULTI_CHAN_CTRL, 0x0007);
939
940	/* Set Surround DAC Volume to 0dB
941	 * Set Center/LFE DAC Volume to 0dB
942	 * (but both should already be set, as these are hardware reset defaults)
943	 */
944	ac97_reg_cached_write(dev, AC97_ALC650_SURR_VOLUME, 0x0808);
945	ac97_reg_cached_write(dev, AC97_ALC650_CEN_LFE_VOLUME, 0x0808);
946}
947
948
949void
950alc655_init(ac97_dev *dev)
951{
952	uint16 val;
953	LOG(("alc655_init\n"));
954
955	ac97_reg_update_bits(dev, AC97_PAGING, 0xf, 0);
956
957	val = ac97_reg_cached_read(dev, AC97_ALC650_CLOCK_SOURCE);
958	// TODO update bits for specific devices
959	val &= ~0x1000;
960	ac97_reg_cached_write(dev, AC97_ALC650_CLOCK_SOURCE, val);
961
962	ac97_reg_cached_write(dev, AC97_ALC650_MULTI_CHAN_CTRL, 0x8000);
963	ac97_reg_cached_write(dev, AC97_ALC650_SURR_VOLUME, 0x808);
964	ac97_reg_cached_write(dev, AC97_ALC650_CEN_LFE_VOLUME, 0x808);
965
966	if (dev->codec_id == 0x414c4781)
967		ac97_reg_update_bits(dev, AC97_ALC650_MISC_CONTROL, 0x800, 0x800);
968}
969
970
971void
972alc850_init(ac97_dev *dev)
973{
974	LOG(("alc850_init\n"));
975
976	ac97_reg_update_bits(dev, AC97_PAGING, 0xf, 0);
977
978	ac97_reg_cached_write(dev, AC97_ALC650_MULTI_CHAN_CTRL, 0x8000);
979	ac97_reg_cached_write(dev, AC97_ALC650_CLOCK_SOURCE, 0x20d2);
980	ac97_reg_cached_write(dev, AC97_ALC650_GPIO_SETUP, 0x8a90);
981	ac97_reg_cached_write(dev, AC97_ALC650_SURR_VOLUME, 0x808);
982	ac97_reg_cached_write(dev, AC97_ALC650_CEN_LFE_VOLUME, 0x808);
983}
984
985
986void
987stac9708_init(ac97_dev *dev)
988{
989	LOG(("stac9708_init\n"));
990	/* ALSA initializes some registers that according to the
991	 * documentation for this codec do not exist. If the
992	 * following doesn't work, we may need to do that, too.
993	 */
994	/* The Analog Special reg is at 0x6C, other codecs have it at 0x6E */
995	/* Set Analog Special to default (DAC/ADC -6dB disabled) */
996	ac97_reg_cached_write(dev, 0x6C, 0x0000);
997	/* Set Multi Channel to default */
998	ac97_reg_cached_write(dev, 0x74, 0x0000);
999}
1000
1001
1002void
1003stac9721_init(ac97_dev *dev)
1004{
1005	LOG(("stac9721_init\n"));
1006	/* Set Analog Special to default (DAC/ADC -6dB disabled) */
1007	ac97_reg_cached_write(dev, 0x6E, 0x0000);
1008	/* Enable register 0x72 */
1009	ac97_reg_cached_write(dev, 0x70, 0xabba);
1010	/* Set Analog Current to -50% */
1011	ac97_reg_cached_write(dev, 0x72, 0x0002);
1012	/* Set Multi Channel to default */
1013	ac97_reg_cached_write(dev, 0x74, 0x0000);
1014	/* Enable register 0x78 */
1015	ac97_reg_cached_write(dev, 0x76, 0xabba);
1016	/* Set Clock Access to default */
1017	ac97_reg_cached_write(dev, 0x78, 0x0000);
1018}
1019
1020
1021void
1022stac9744_init(ac97_dev *dev)
1023{
1024	LOG(("stac9744_init\n"));
1025	/* Set Analog Special to default (DAC/ADC -6dB disabled) */
1026	ac97_reg_cached_write(dev, 0x6E, 0x0000);
1027	/* Enable register 0x72 */
1028	ac97_reg_cached_write(dev, 0x70, 0xabba);
1029	/* Set Analog Current to -50% */
1030	ac97_reg_cached_write(dev, 0x72, 0x0002);
1031	/* Set Multi Channel to default */
1032	ac97_reg_cached_write(dev, 0x74, 0x0000);
1033	/* Enable register 0x78 */
1034	ac97_reg_cached_write(dev, 0x76, 0xabba);
1035	/* Set Clock Access to default */
1036	ac97_reg_cached_write(dev, 0x78, 0x0000);
1037}
1038
1039
1040void
1041stac9756_init(ac97_dev *dev)
1042{
1043	LOG(("stac9756_init\n"));
1044	/* Set Analog Special to default (AC97 all-mix, DAC/ADC -6dB disabled) */
1045	ac97_reg_cached_write(dev, 0x6E, 0x1000);
1046	/* Enable register 0x72 */
1047	ac97_reg_cached_write(dev, 0x70, 0xabba);
1048	/* Set Analog Current to -50% */
1049	ac97_reg_cached_write(dev, 0x72, 0x0002);
1050	/* Set Multi Channel to default */
1051	ac97_reg_cached_write(dev, 0x74, 0x0000);
1052	/* Enable register 0x78 */
1053	ac97_reg_cached_write(dev, 0x76, 0xabba);
1054	/* Set Clock Access to default */
1055	ac97_reg_cached_write(dev, 0x78, 0x0000);
1056}
1057
1058
1059
1060void
1061stac9758_init(ac97_dev *dev)
1062{
1063	LOG(("stac9758_init\n"));
1064
1065	ac97_reg_update_bits(dev, AC97_PAGING, 0xf, 0);
1066
1067	if (dev->subsystem == 0x107b0601) {
1068		ac97_reg_cached_write(dev, 0x64, 0xfc70);
1069		ac97_reg_cached_write(dev, 0x68, 0x2102);
1070		ac97_reg_cached_write(dev, 0x66, 0x0203);
1071		ac97_reg_cached_write(dev, 0x72, 0x0041);
1072	} else {
1073		ac97_reg_cached_write(dev, 0x64, 0xd794);
1074		ac97_reg_cached_write(dev, 0x68, 0x2001);
1075		ac97_reg_cached_write(dev, 0x66, 0x0201);
1076		ac97_reg_cached_write(dev, 0x72, 0x0040);
1077	}
1078}
1079
1080
1081void
1082tr28028_init(ac97_dev *dev)
1083{
1084	LOG(("tr28028_init\n"));
1085	ac97_reg_cached_write(dev, AC97_POWERDOWN, 0x0300);
1086	ac97_reg_cached_write(dev, AC97_POWERDOWN, 0x0000);
1087	ac97_reg_cached_write(dev, AC97_SURR_VOLUME, 0x0000);
1088	ac97_reg_cached_write(dev, AC97_SPDIF_CONTROL, 0x0000);
1089}
1090
1091
1092void
1093wm9701_init(ac97_dev *dev)
1094{
1095	LOG(("wm9701_init\n"));
1096	/* ALSA writes some of these registers, but the codec
1097	 * documentation states explicitly that 0x38 and 0x70 to 0x74
1098	 * are not used in the WM9701A
1099	 */
1100
1101	/* DVD noise patch (?) */
1102	ac97_reg_cached_write(dev, 0x5a, 0x0200);
1103}
1104
1105
1106void
1107wm9703_init(ac97_dev *dev)
1108{
1109	LOG(("wm9703_init\n"));
1110	/* Set front mixer value to unmuted */
1111	ac97_reg_cached_write(dev, 0x72, 0x0808);
1112	/* Disable loopback, etc */
1113	ac97_reg_cached_write(dev, AC97_GENERAL_PURPOSE, 0x8000);
1114}
1115
1116
1117void
1118wm9704_init(ac97_dev *dev)
1119{
1120	LOG(("wm9704_init\n"));
1121	/* Set read DAC value to unmuted */
1122	ac97_reg_cached_write(dev, 0x70, 0x0808);
1123	/* Set front mixer value to unmuted */
1124	ac97_reg_cached_write(dev, 0x72, 0x0808);
1125	/* Set rear mixer value to unmuted */
1126	ac97_reg_cached_write(dev, 0x74, 0x0808);
1127	/* DVD noise patch (?) */
1128	ac97_reg_cached_write(dev, 0x5a, 0x0200);
1129}
1130
1131
1132const ac97_source_info source_info[] = {
1133	{ "Recording", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO|B_MIX_RECORDMUX, 100, AC97_RECORD_GAIN, 0x8000, 4, 0, 1, 0, 0.0, 22.5, 1.5 },
1134	{ "Master", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 101, AC97_MASTER_VOLUME, 0x8000, 5, 0, 1, 1,-46.5, 0.0, 1.5 },
1135	//{ "Bass/Treble", B_MIX_GAIN|B_MIX_STEREO, 102, AC97_MASTER_TONE, 0x0f0f, 4, 0, 1, 1,-12.0, 10.5, 1.5 },
1136	//{ "Aux out", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 103, AC97_AUX_OUT_VOLUME, 0x8000, 5, 0, 1, 1,-46.5, 0.0, 1.5 },
1137	{ "PCM out", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 104, AC97_PCM_OUT_VOLUME, 0x8808, 5, 0, 1, 1,-34.5, 12.0, 1.5 },
1138	{ "CD", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 105, AC97_CD_VOLUME, 0x8808, 5, 0, 1, 1,-34.5, 12.0, 1.5 },
1139	{ "Aux In", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 106, AC97_AUX_IN_VOLUME, 0x8808, 5, 0, 1, 1,-34.5, 12.0, 1.5 },
1140	{ "TAD", B_MIX_GAIN|B_MIX_MUTE|B_MIX_MONO, 107, AC97_PHONE_VOLUME, 0x8008, 5, 0, 1, 1,-34.5, 12.0, 1.5 },
1141	{ "Mic", B_MIX_GAIN|B_MIX_MUTE|B_MIX_MONO|B_MIX_MICBOOST, 108, AC97_MIC_VOLUME, 0x8008, 5, 0, 1, 1,-34.5, 12.0, 1.5 },
1142	{ "Line in", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 109, AC97_LINE_IN_VOLUME, 0x8808, 5, 0, 1, 1,-34.5, 12.0, 1.5 },
1143	//{ "Center/Lfe", B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 111, AC97_CENTER_LFE_VOLUME, 0x8080, 5, 0, 1, 1,-46.5, 0.0, 1.5 },
1144	{ "Center/Lfe" /* should be "Surround" but no */, B_MIX_GAIN|B_MIX_MUTE|B_MIX_STEREO, 110, AC97_SURR_VOLUME, 0x8080, 5, 0, 1, 1,-46.5, 0.0, 1.5 }
1145};
1146
1147const int32 source_info_size = (sizeof(source_info)/sizeof(source_info[0]));
1148