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
43 bool ac97_reg_is_valid(ac97_dev *dev, uint8 reg);
44 void ac97_amp_enable(ac97_dev *dev, bool onoff);
45 void ac97_dump_capabilities(ac97_dev *dev);
46 void ac97_detect_capabilities(ac97_dev *dev);
47 void ac97_detect_rates(ac97_dev *dev);
48 void ac97_update_register_cache(ac97_dev *dev);
49
50
51 const 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
88 static void default_init(ac97_dev *dev);
89 static void ad1819_init(ac97_dev *dev);
90 static void ad1881_init(ac97_dev *dev);
91 static void ad1885_init(ac97_dev *dev);
92 static void ad1886_init(ac97_dev *dev);
93 static void ad1980_init(ac97_dev *dev);
94 static void ad1981b_init(ac97_dev *dev);
95 static void alc203_init(ac97_dev *dev);
96 static void alc650_init(ac97_dev *dev);
97 static void alc655_init(ac97_dev *dev);
98 static void alc850_init(ac97_dev *dev);
99 static void stac9708_init(ac97_dev *dev);
100 static void stac9721_init(ac97_dev *dev);
101 static void stac9744_init(ac97_dev *dev);
102 static void stac9756_init(ac97_dev *dev);
103 static void stac9758_init(ac97_dev *dev);
104 static void tr28028_init(ac97_dev *dev);
105 static void wm9701_init(ac97_dev *dev);
106 static void wm9703_init(ac97_dev *dev);
107 static void wm9704_init(ac97_dev *dev);
108
109 bool ad1819_set_rate(ac97_dev *dev, uint8 reg, uint32 rate);
110 bool ad1819_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate);
111
112
113 typedef struct
114 {
115 uint32 id;
116 uint32 mask;
117 codec_init init;
118 const char *info;
119 } codec_table;
120
121
122 codec_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
228 static codec_table *
find_codec_table(uint32 codecid)229 find_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
239 void
ac97_attach(ac97_dev ** _dev,codec_reg_read reg_read,codec_reg_write reg_write,void * cookie,ushort subvendor_id,ushort subsystem_id)240 ac97_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
324 void
ac97_detach(ac97_dev * dev)325 ac97_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
343 void
ac97_suspend(ac97_dev * dev)344 ac97_suspend(ac97_dev *dev)
345 {
346 ac97_amp_enable(dev, false);
347 }
348
349
350 void
ac97_resume(ac97_dev * dev)351 ac97_resume(ac97_dev *dev)
352 {
353 ac97_amp_enable(dev, true);
354 }
355
356
357 void
ac97_reg_cached_write(ac97_dev * dev,uint8 reg,uint16 value)358 ac97_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
367 uint16
ac97_reg_cached_read(ac97_dev * dev,uint8 reg)368 ac97_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
375 void
ac97_reg_uncached_write(ac97_dev * dev,uint8 reg,uint16 value)376 ac97_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
384 uint16
ac97_reg_uncached_read(ac97_dev * dev,uint8 reg)385 ac97_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
393 bool
ac97_reg_update(ac97_dev * dev,uint8 reg,uint16 value)394 ac97_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
405 bool
ac97_reg_update_bits(ac97_dev * dev,uint8 reg,uint16 mask,uint16 value)406 ac97_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
421 void
ac97_update_register_cache(ac97_dev * dev)422 ac97_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
430 bool
ac97_set_rate(ac97_dev * dev,uint8 reg,uint32 rate)431 ac97_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
465 bool
ac97_get_rate(ac97_dev * dev,uint8 reg,uint32 * rate)466 ac97_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
486 void
ac97_set_clock(ac97_dev * dev,uint32 clock)487 ac97_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
496 void
ac97_detect_capabilities(ac97_dev * dev)497 ac97_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
550 void
ac97_detect_rates(ac97_dev * dev)551 ac97_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
597 void
ac97_dump_capabilities(ac97_dev * dev)598 ac97_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
668 bool
ac97_has_capability(ac97_dev * dev,uint64 cap)669 ac97_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
679 bool
ac97_reg_is_valid(ac97_dev * dev,uint8 reg)680 ac97_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
726 void
ac97_amp_enable(ac97_dev * dev,bool yesno)727 ac97_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
755 bool
ad1819_set_rate(ac97_dev * dev,uint8 reg,uint32 rate)756 ad1819_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
785 bool
ad1819_get_rate(ac97_dev * dev,uint8 reg,uint32 * rate)786 ad1819_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
808 void
default_init(ac97_dev * dev)809 default_init(ac97_dev *dev)
810 {
811 LOG(("default_init\n"));
812 }
813
814
815 void
ad1819_init(ac97_dev * dev)816 ad1819_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
839 void
ad1881_init(ac97_dev * dev)840 ad1881_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
858 void
ad1885_init(ac97_dev * dev)859 ad1885_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
869 void
ad1886_init(ac97_dev * dev)870 ad1886_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
882 void
ad1980_init(ac97_dev * dev)883 ad1980_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
902 void
ad1981b_init(ac97_dev * dev)903 ad1981b_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
921 void
alc203_init(ac97_dev * dev)922 alc203_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
930 void
alc650_init(ac97_dev * dev)931 alc650_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
949 void
alc655_init(ac97_dev * dev)950 alc655_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
971 void
alc850_init(ac97_dev * dev)972 alc850_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
986 void
stac9708_init(ac97_dev * dev)987 stac9708_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
1002 void
stac9721_init(ac97_dev * dev)1003 stac9721_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
1021 void
stac9744_init(ac97_dev * dev)1022 stac9744_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
1040 void
stac9756_init(ac97_dev * dev)1041 stac9756_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
1060 void
stac9758_init(ac97_dev * dev)1061 stac9758_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
1081 void
tr28028_init(ac97_dev * dev)1082 tr28028_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
1092 void
wm9701_init(ac97_dev * dev)1093 wm9701_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
1106 void
wm9703_init(ac97_dev * dev)1107 wm9703_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
1117 void
wm9704_init(ac97_dev * dev)1118 wm9704_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
1132 const 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
1147 const int32 source_info_size = (sizeof(source_info)/sizeof(source_info[0]));
1148