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