FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/ac97.c
1 /* $OpenBSD: ac97.c,v 1.84 2018/04/11 04:48:31 ratchov Exp $ */
2
3 /*
4 * Copyright (c) 1999, 2000 Constantine Sapuntzakis
5 *
6 * Author: Constantine Sapuntzakis <csapuntz@stanford.edu>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
25 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
29 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 * DAMAGE. */
31
32 /* Partially inspired by FreeBSD's sys/dev/pcm/ac97.c. It came with
33 the following copyright */
34
35 /*
36 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
37 * All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * $FreeBSD$
61 */
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/malloc.h>
67
68 #include <sys/audioio.h>
69 #include <dev/audio_if.h>
70 #include <dev/ic/ac97.h>
71
72
73 /* default parameters; supported by all ac97 codecs */
74 const struct audio_params ac97_audio_default = {
75 48000, /* sample_rate */
76 AUDIO_ENCODING_SLINEAR_LE, /* encoding */
77 16, /* precision */
78 2, /* bps */
79 1, /* msb */
80 2 /* channels */
81 };
82
83 const struct audio_mixer_enum ac97_on_off = {
84 2,
85 { { { AudioNoff } , 0 },
86 { { AudioNon } , 1 } }
87 };
88
89 const struct audio_mixer_enum ac97_mic_select = {
90 2,
91 { { { AudioNmicrophone "" }, 0 },
92 { { AudioNmicrophone "1" }, 1 } }
93 };
94
95 const struct audio_mixer_enum ac97_mono_select = {
96 2,
97 { { { AudioNmixerout }, 0 },
98 { { AudioNmicrophone }, 1 } }
99 };
100
101 const struct audio_mixer_enum ac97_source = {
102 8,
103 { { { AudioNmicrophone } , 0 },
104 { { AudioNcd }, 1 },
105 { { "video" }, 2 },
106 { { AudioNaux }, 3 },
107 { { AudioNline }, 4 },
108 { { AudioNmixerout }, 5 },
109 { { AudioNmixerout AudioNmono }, 6 },
110 { { "phone" }, 7 }}
111 };
112
113 /*
114 * Due to different values for each source that uses these structures,
115 * the ac97_query_devinfo function sets delta in mixer_devinfo_t using
116 * ac97_source_info.bits.
117 */
118 const struct audio_mixer_value ac97_volume_stereo = {
119 { AudioNvolume },
120 2
121 };
122
123 const struct audio_mixer_value ac97_volume_mono = {
124 { AudioNvolume },
125 1
126 };
127
128 #define AudioNspdif "spdif"
129
130 #define WRAP(a) &a, sizeof(a)
131
132 const struct ac97_source_info {
133 char *class;
134 char *device;
135 char *qualifier;
136 int type;
137
138 const void *info;
139 int16_t info_size;
140
141 u_int8_t reg;
142 u_int16_t default_value;
143 u_int8_t bits:3;
144 u_int8_t ofs:4;
145 u_int8_t mute:1;
146 u_int8_t polarity:1; /* Does 0 == MAX or MIN */
147 enum {
148 CHECK_NONE = 0,
149 CHECK_SURROUND,
150 CHECK_CENTER,
151 CHECK_LFE,
152 CHECK_HEADPHONES,
153 CHECK_TONE,
154 CHECK_MIC,
155 CHECK_LOUDNESS,
156 CHECK_3D,
157 CHECK_SPDIF
158 } req_feature;
159
160 int16_t prev;
161 int16_t next;
162 int16_t mixer_class;
163 } source_info[] = {
164 { AudioCinputs, NULL, NULL,
165 AUDIO_MIXER_CLASS, },
166 { AudioCoutputs, NULL, NULL,
167 AUDIO_MIXER_CLASS, },
168 { AudioCrecord, NULL, NULL,
169 AUDIO_MIXER_CLASS, },
170 /* Stereo master volume*/
171 { AudioCoutputs, AudioNmaster, NULL,
172 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
173 AC97_REG_MASTER_VOLUME, 0x8000, 5, 0, 1,
174 },
175 /* Mono volume */
176 { AudioCoutputs, AudioNmono, NULL,
177 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
178 AC97_REG_MASTER_VOLUME_MONO, 0x8000, 6, 0, 1,
179 },
180 { AudioCoutputs, AudioNmono, AudioNsource,
181 AUDIO_MIXER_ENUM, WRAP(ac97_mono_select),
182 AC97_REG_GP, 0x0000, 1, 9, 0,
183 },
184 /* Headphone volume */
185 { AudioCoutputs, AudioNheadphone, NULL,
186 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
187 AC97_REG_HEADPHONE_VOLUME, 0x8000, 6, 0, 1, 0, CHECK_HEADPHONES
188 },
189 /* Surround volume - logic hard coded for mute */
190 { AudioCoutputs, AudioNsurround, NULL,
191 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
192 AC97_REG_SURR_MASTER, 0x8080, 5, 0, 1, 0, CHECK_SURROUND
193 },
194 /* Center volume*/
195 { AudioCoutputs, AudioNcenter, NULL,
196 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
197 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 0, 0, 0, CHECK_CENTER
198 },
199 { AudioCoutputs, AudioNcenter, AudioNmute,
200 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
201 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 7, 0, 0, CHECK_CENTER
202 },
203 /* LFE volume*/
204 { AudioCoutputs, AudioNlfe, NULL,
205 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
206 AC97_REG_CENTER_LFE_MASTER, 0x8080, 5, 8, 0, 0, CHECK_LFE
207 },
208 { AudioCoutputs, AudioNlfe, AudioNmute,
209 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
210 AC97_REG_CENTER_LFE_MASTER, 0x8080, 1, 15, 0, 0, CHECK_LFE
211 },
212 /* Tone */
213 { AudioCoutputs, "tone", NULL,
214 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
215 AC97_REG_MASTER_TONE, 0x0f0f, 4, 0, 0, 0, CHECK_TONE
216 },
217 /* PC Beep Volume */
218 { AudioCinputs, AudioNspeaker, NULL,
219 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
220 AC97_REG_PCBEEP_VOLUME, 0x0000, 4, 1, 1,
221 },
222
223 /* Phone */
224 { AudioCinputs, "phone", NULL,
225 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
226 AC97_REG_PHONE_VOLUME, 0x8008, 5, 0, 1,
227 },
228 /* Mic Volume */
229 { AudioCinputs, AudioNmicrophone, NULL,
230 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
231 AC97_REG_MIC_VOLUME, 0x8008, 5, 0, 1,
232 },
233 { AudioCinputs, AudioNmicrophone, AudioNpreamp,
234 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
235 AC97_REG_MIC_VOLUME, 0x8008, 1, 6, 0,
236 },
237 { AudioCinputs, AudioNmicrophone, AudioNsource,
238 AUDIO_MIXER_ENUM, WRAP(ac97_mic_select),
239 AC97_REG_GP, 0x0000, 1, 8, 0,
240 },
241 /* Line in Volume */
242 { AudioCinputs, AudioNline, NULL,
243 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
244 AC97_REG_LINEIN_VOLUME, 0x8808, 5, 0, 1,
245 },
246 /* CD Volume */
247 { AudioCinputs, AudioNcd, NULL,
248 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
249 AC97_REG_CD_VOLUME, 0x8808, 5, 0, 1,
250 },
251 /* Video Volume */
252 { AudioCinputs, AudioNvideo, NULL,
253 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
254 AC97_REG_VIDEO_VOLUME, 0x8808, 5, 0, 1,
255 },
256 /* AUX volume */
257 { AudioCinputs, AudioNaux, NULL,
258 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
259 AC97_REG_AUX_VOLUME, 0x8808, 5, 0, 1,
260 },
261 /* PCM out volume */
262 { AudioCinputs, AudioNdac, NULL,
263 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
264 AC97_REG_PCMOUT_VOLUME, 0x8808, 5, 0, 1,
265 },
266 /* Record Source - some logic for this is hard coded - see below */
267 { AudioCrecord, AudioNsource, NULL,
268 AUDIO_MIXER_ENUM, WRAP(ac97_source),
269 AC97_REG_RECORD_SELECT, 0x0000, 3, 0, 0,
270 },
271 /* Record Gain */
272 { AudioCrecord, AudioNvolume, NULL,
273 AUDIO_MIXER_VALUE, WRAP(ac97_volume_stereo),
274 AC97_REG_RECORD_GAIN, 0x8000, 4, 0, 1,
275 },
276 /* Record Gain mic */
277 { AudioCrecord, AudioNmicrophone, NULL,
278 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
279 AC97_REG_RECORD_GAIN_MIC, 0x8000, 4, 0, 1, 1, CHECK_MIC
280 },
281 /* */
282 { AudioCoutputs, AudioNloudness, NULL,
283 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
284 AC97_REG_GP, 0x0000, 1, 12, 0, 0, CHECK_LOUDNESS
285 },
286 { AudioCoutputs, AudioNspatial, NULL,
287 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
288 AC97_REG_GP, 0x0000, 1, 13, 0, 1, CHECK_3D
289 },
290 { AudioCoutputs, AudioNspatial, "center",
291 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
292 AC97_REG_3D_CONTROL, 0x0000, 4, 8, 0, 1, CHECK_3D
293 },
294 { AudioCoutputs, AudioNspatial, "depth",
295 AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono),
296 AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, CHECK_3D
297 },
298 /* External Amp */
299 { AudioCoutputs, AudioNextamp, NULL,
300 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
301 AC97_REG_POWER, 0x0000, 1, 15, 0, 0
302 },
303 /* S/PDIF output enable */
304 { AudioCoutputs, AudioNspdif, NULL,
305 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
306 AC97_REG_EXT_AUDIO_CTRL, 0x0000, 1, 2, 0, 0, CHECK_SPDIF
307 }
308
309 /* Missing features: Simulated Stereo, POP, Loopback mode */
310 };
311
312 /*
313 * Check out http://www.intel.com/technology/computing/audio/index.htm
314 * for information on AC-97
315 */
316
317 struct ac97_softc {
318 /* ac97_codec_if must be at the first of ac97_softc. */
319 struct ac97_codec_if codec_if;
320 struct ac97_host_if *host_if;
321 #define MAX_SOURCES (2 * nitems(source_info))
322 struct ac97_source_info source_info[MAX_SOURCES];
323 int num_source_info;
324 enum ac97_host_flags host_flags;
325 unsigned int ac97_clock; /* usually 48000 */
326 #define AC97_STANDARD_CLOCK 48000U
327 u_int16_t caps; /* -> AC97_REG_RESET */
328 u_int16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */
329 u_int16_t shadow_reg[128];
330 int lock_counter;
331 };
332
333 int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *);
334 int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *);
335 void ac97_lock(struct ac97_codec_if *);
336 void ac97_unlock(struct ac97_codec_if *);
337 int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *);
338 int ac97_get_portnum_by_name(struct ac97_codec_if *, char *, char *,
339 char *);
340 int ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate);
341 void ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock);
342 u_int16_t ac97_get_extcaps(struct ac97_codec_if *codec_if);
343 int ac97_add_port(struct ac97_softc *as, struct ac97_source_info *src);
344
345 void ac97_ad1885_init(struct ac97_softc *, int);
346 void ac97_ad1886_init(struct ac97_softc *, int);
347 void ac97_ad198x_init(struct ac97_softc *, int);
348 void ac97_alc650_init(struct ac97_softc *, int);
349 void ac97_cx20468_init(struct ac97_softc *, int);
350 void ac97_vt1616_init(struct ac97_softc *, int);
351
352 struct ac97_codec_if_vtbl ac97civ = {
353 ac97_mixer_get_port,
354 ac97_mixer_set_port,
355 ac97_query_devinfo,
356 ac97_get_portnum_by_name,
357 ac97_get_extcaps,
358 ac97_set_rate,
359 ac97_set_clock,
360 ac97_lock,
361 ac97_unlock
362 };
363
364 const struct ac97_codecid {
365 u_int8_t id;
366 u_int8_t mask;
367 u_int8_t rev;
368 u_int8_t shift; /* no use yet */
369 char * const name;
370 void (*init)(struct ac97_softc *, int);
371 } ac97_ad[] = {
372 { 0x03, 0xff, 0, 0, "AD1819" },
373 { 0x40, 0xff, 0, 0, "AD1881" },
374 { 0x48, 0xff, 0, 0, "AD1881A" },
375 { 0x60, 0xff, 0, 0, "AD1885", ac97_ad1885_init },
376 { 0x61, 0xff, 0, 0, "AD1886", ac97_ad1886_init },
377 { 0x63, 0xff, 0, 0, "AD1886A" },
378 { 0x68, 0xff, 0, 0, "AD1888", ac97_ad198x_init },
379 { 0x70, 0xff, 0, 0, "AD1980", ac97_ad198x_init },
380 { 0x72, 0xff, 0, 0, "AD1981A" },
381 { 0x74, 0xff, 0, 0, "AD1981B" },
382 { 0x75, 0xff, 0, 0, "AD1985", ac97_ad198x_init },
383 }, ac97_ak[] = {
384 { 0x00, 0xfe, 1, 0, "AK4540" },
385 { 0x01, 0xfe, 1, 0, "AK4540" },
386 { 0x02, 0xff, 0, 0, "AK4543" },
387 { 0x05, 0xff, 0, 0, "AK4544" },
388 { 0x06, 0xff, 0, 0, "AK4544A" },
389 { 0x07, 0xff, 0, 0, "AK4545" },
390 }, ac97_av[] = {
391 { 0x10, 0xff, 0, 0, "ALC200" },
392 { 0x20, 0xff, 0, 0, "ALC650" },
393 { 0x21, 0xff, 0, 0, "ALC650D" },
394 { 0x22, 0xff, 0, 0, "ALC650E" },
395 { 0x23, 0xff, 0, 0, "ALC650F" },
396 { 0x30, 0xff, 0, 0, "ALC101" },
397 { 0x40, 0xff, 0, 0, "ALC202" },
398 { 0x50, 0xff, 0, 0, "ALC250" },
399 { 0x52, 0xff, 0, 0, "ALC250A?" },
400 { 0x60, 0xf0, 0xf, 0, "ALC655", ac97_alc650_init },
401 { 0x70, 0xf0, 0xf, 0, "ALC203" },
402 { 0x80, 0xf0, 0xf, 0, "ALC658", ac97_alc650_init },
403 { 0x90, 0xf0, 0xf, 0, "ALC850" },
404 }, ac97_rl[] = {
405 { 0x00, 0xf0, 0xf, 0, "RL5306" },
406 { 0x10, 0xf0, 0xf, 0, "RL5382" },
407 { 0x20, 0xf0, 0xf, 0, "RL5383" },
408 }, ac97_cm[] = {
409 { 0x41, 0xff, 0, 0, "CMI9738" },
410 { 0x61, 0xff, 0, 0, "CMI9739" },
411 { 0x78, 0xff, 0, 0, "CMI9761A" },
412 { 0x82, 0xff, 0, 0, "CMI9761B" },
413 { 0x83, 0xff, 0, 0, "CMI9761A+" },
414 }, ac97_cr[] = {
415 { 0x84, 0xff, 0, 0, "EV1938" },
416 }, ac97_cs[] = {
417 { 0x00, 0xf8, 7, 0, "CS4297" },
418 { 0x10, 0xf8, 7, 0, "CS4297A" },
419 { 0x20, 0xf8, 7, 0, "CS4298" },
420 { 0x28, 0xf8, 7, 0, "CS4294" },
421 { 0x30, 0xf8, 7, 0, "CS4299" },
422 { 0x48, 0xf8, 7, 0, "CS4201" },
423 { 0x58, 0xf8, 7, 0, "CS4205" },
424 { 0x60, 0xf8, 7, 0, "CS4291" },
425 { 0x70, 0xf8, 7, 0, "CS4202" },
426 }, ac97_cx[] = {
427 { 0x21, 0xff, 0, 0, "HSD11246" },
428 { 0x28, 0xf8, 7, 0, "CX20468", ac97_cx20468_init },
429 { 0x30, 0xff, 0, 0, "CXT48", },
430 { 0x42, 0xff, 0, 0, "CXT66", },
431 }, ac97_dt[] = {
432 { 0x00, 0xff, 0, 0, "DT0398" },
433 }, ac97_em[] = {
434 { 0x23, 0xff, 0, 0, "EM28023" },
435 { 0x28, 0xff, 0, 0, "EM28028" },
436 }, ac97_es[] = {
437 { 0x08, 0xff, 0, 0, "ES1921" },
438 }, ac97_is[] = {
439 { 0x00, 0xff, 0, 0, "HMP9701" },
440 }, ac97_ic[] = {
441 { 0x01, 0xff, 0, 0, "ICE1230" },
442 { 0x11, 0xff, 0, 0, "ICE1232" },
443 { 0x14, 0xff, 0, 0, "ICE1232A" },
444 { 0x51, 0xff, 0, 0, "VIA VT1616" },
445 { 0x52, 0xff, 0, 0, "VIA VT1616i", ac97_vt1616_init },
446 }, ac97_it[] = {
447 { 0x20, 0xff, 0, 0, "ITE2226E" },
448 { 0x60, 0xff, 0, 0, "ITE2646E" },
449 }, ac97_ns[] = {
450 { 0x00, 0xff, 0, 0, "LM454[03568]" },
451 { 0x31, 0xff, 0, 0, "LM4549" },
452 { 0x40, 0xff, 0, 0, "LM4540" },
453 { 0x43, 0xff, 0, 0, "LM4543" },
454 { 0x46, 0xff, 0, 0, "LM4546A" },
455 { 0x48, 0xff, 0, 0, "LM4548A" },
456 { 0x49, 0xff, 0, 0, "LM4549A" },
457 { 0x50, 0xff, 0, 0, "LM4550" },
458 }, ac97_ps[] = {
459 { 0x01, 0xff, 0, 0, "UCB1510" },
460 { 0x04, 0xff, 0, 0, "UCB1400" },
461 }, ac97_sl[] = {
462 { 0x20, 0xe0, 0, 0, "Si3036/38" },
463 }, ac97_st[] = {
464 { 0x00, 0xff, 0, 0, "STAC9700" },
465 { 0x04, 0xff, 0, 0, "STAC970[135]" },
466 { 0x05, 0xff, 0, 0, "STAC9704" },
467 { 0x08, 0xff, 0, 0, "STAC9708/11" },
468 { 0x09, 0xff, 0, 0, "STAC9721/23" },
469 { 0x44, 0xff, 0, 0, "STAC9744/45" },
470 { 0x50, 0xff, 0, 0, "STAC9750/51" },
471 { 0x52, 0xff, 0, 0, "STAC9752/53" },
472 { 0x56, 0xff, 0, 0, "STAC9756/57" },
473 { 0x58, 0xff, 0, 0, "STAC9758/59" },
474 { 0x60, 0xff, 0, 0, "STAC9760/61" },
475 { 0x62, 0xff, 0, 0, "STAC9762/63" },
476 { 0x66, 0xff, 0, 0, "STAC9766/67" },
477 { 0x84, 0xff, 0, 0, "STAC9784/85" },
478 }, ac97_vi[] = {
479 { 0x61, 0xff, 0, 0, "VT1612A" },
480 { 0x70, 0xff, 0, 0, "VT1617" },
481 }, ac97_tt[] = {
482 { 0x02, 0xff, 0, 0, "TR28022" },
483 { 0x03, 0xff, 0, 0, "TR28023" },
484 { 0x06, 0xff, 0, 0, "TR28026" },
485 { 0x08, 0xff, 0, 0, "TR28028" },
486 { 0x23, 0xff, 0, 0, "TR28602" },
487 }, ac97_ti[] = {
488 { 0x20, 0xff, 0, 0, "TLC320AD9xC" },
489 }, ac97_wb[] = {
490 { 0x01, 0xff, 0, 0, "W83971D" },
491 }, ac97_wo[] = {
492 { 0x00, 0xff, 0, 0, "WM9701A" },
493 { 0x03, 0xff, 0, 0, "WM9704M/Q-0" }, /* & WM9703 */
494 { 0x04, 0xff, 0, 0, "WM9704M/Q-1" },
495 { 0x05, 0xff, 0, 0, "WM9705/10" },
496 { 0x09, 0xff, 0, 0, "WM9709" },
497 { 0x12, 0xff, 0, 0, "WM9711/12" },
498 }, ac97_ym[] = {
499 { 0x00, 0xff, 0, 0, "YMF743-S" },
500 { 0x02, 0xff, 0, 0, "YMF752-S" },
501 { 0x03, 0xff, 0, 0, "YMF753-S" },
502 };
503
504 #define cl(n) n, nitems(n)
505 const struct ac97_vendorid {
506 u_int32_t id;
507 char * const name;
508 const struct ac97_codecid * const codecs;
509 u_int8_t num;
510 } ac97_vendors[] = {
511 { 0x01408300, "Creative", cl(ac97_cr) },
512 { 0x41445300, "Analog Devices", cl(ac97_ad) },
513 { 0x414b4D00, "Asahi Kasei", cl(ac97_ak) },
514 { 0x414c4300, "Realtek", cl(ac97_rl) },
515 { 0x414c4700, "Avance Logic", cl(ac97_av) },
516 { 0x434d4900, "C-Media Electronics", cl(ac97_cm) },
517 { 0x43525900, "Cirrus Logic", cl(ac97_cs) },
518 { 0x43585400, "Conexant", cl(ac97_cx) },
519 { 0x44543000, "Diamond Technology", cl(ac97_dt) },
520 { 0x454d4300, "eMicro", cl(ac97_em) },
521 { 0x45838300, "ESS Technology", cl(ac97_es) },
522 { 0x48525300, "Intersil", cl(ac97_is) },
523 { 0x49434500, "ICEnsemble", cl(ac97_ic) },
524 { 0x49544500, "ITE, Inc.", cl(ac97_it) },
525 { 0x4e534300, "National Semiconductor", cl(ac97_ns) },
526 { 0x50534300, "Philips Semiconductor", cl(ac97_ps) },
527 { 0x53494c00, "Silicon Laboratory", cl(ac97_sl) },
528 { 0x54524100, "TriTech Microelectronics", cl(ac97_tt) },
529 { 0x54584e00, "Texas Instruments", cl(ac97_ti) },
530 { 0x56494100, "VIA Technologies", cl(ac97_vi) },
531 { 0x57454300, "Winbond", cl(ac97_wb) },
532 { 0x574d4c00, "Wolfson", cl(ac97_wo) },
533 { 0x594d4800, "Yamaha", cl(ac97_ym) },
534 { 0x83847600, "SigmaTel", cl(ac97_st) },
535 };
536 #undef cl
537
538 const char * const ac97enhancement[] = {
539 "No 3D Stereo",
540 "Analog Devices Phat Stereo",
541 "Creative",
542 "National Semi 3D",
543 "Yamaha Ymersion",
544 "BBE 3D",
545 "Crystal Semi 3D",
546 "Qsound QXpander",
547 "Spatializer 3D",
548 "SRS 3D",
549 "Platform Tech 3D",
550 "AKM 3D",
551 "Aureal",
552 "AZTECH 3D",
553 "Binaura 3D",
554 "ESS Technology",
555 "Harman International VMAx",
556 "Nvidea 3D",
557 "Philips Incredible Sound",
558 "Texas Instruments 3D",
559 "VLSI Technology 3D",
560 "TriTech 3D",
561 "Realtek 3D",
562 "Samsung 3D",
563 "Wolfson Microelectronics 3D",
564 "Delta Integration 3D",
565 "SigmaTel 3D",
566 "KS Waves 3D",
567 "Rockwell 3D",
568 "Unknown 3D",
569 "Unknown 3D",
570 "Unknown 3D"
571 };
572
573 const char * const ac97feature[] = {
574 "mic channel",
575 "reserved",
576 "tone",
577 "simulated stereo",
578 "headphone",
579 "bass boost",
580 "18 bit DAC",
581 "20 bit DAC",
582 "18 bit ADC",
583 "20 bit ADC"
584 };
585
586
587 int ac97_str_equal(const char *, const char *);
588 int ac97_check_capability(struct ac97_softc *, int);
589 void ac97_setup_source_info(struct ac97_softc *);
590 void ac97_setup_defaults(struct ac97_softc *);
591 int ac97_read(struct ac97_softc *, u_int8_t, u_int16_t *);
592 int ac97_write(struct ac97_softc *, u_int8_t, u_int16_t);
593
594
595 #ifdef AUDIO_DEBUG
596 #define DPRINTF(x) if (ac97debug) printf x
597 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x
598 #ifdef AC97_DEBUG
599 int ac97debug = 1;
600 #else
601 int ac97debug = 0;
602 #endif
603 #else
604 #define DPRINTF(x)
605 #define DPRINTFN(n,x)
606 #endif
607
608 int
609 ac97_read(struct ac97_softc *as, u_int8_t reg, u_int16_t *val)
610 {
611 int error;
612
613 if (((as->host_flags & AC97_HOST_DONT_READ) &&
614 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
615 reg != AC97_REG_RESET)) ||
616 (as->host_flags & AC97_HOST_DONT_READANY)) {
617 *val = as->shadow_reg[reg >> 1];
618 return (0);
619 }
620
621 if ((error = as->host_if->read(as->host_if->arg, reg, val)))
622 *val = as->shadow_reg[reg >> 1];
623 return (error);
624 }
625
626 int
627 ac97_write(struct ac97_softc *as, u_int8_t reg, u_int16_t val)
628 {
629 as->shadow_reg[reg >> 1] = val;
630 return (as->host_if->write(as->host_if->arg, reg, val));
631 }
632
633 void
634 ac97_setup_defaults(struct ac97_softc *as)
635 {
636 int idx;
637
638 bzero(as->shadow_reg, sizeof(as->shadow_reg));
639
640 for (idx = 0; idx < nitems(source_info); idx++) {
641 const struct ac97_source_info *si = &source_info[idx];
642
643 ac97_write(as, si->reg, si->default_value);
644 }
645 }
646
647 int
648 ac97_str_equal(const char *a, const char *b)
649 {
650 return ((a == b) || (a && b && (!strcmp(a, b))));
651 }
652
653 int
654 ac97_check_capability(struct ac97_softc *as, int check)
655 {
656 switch (check) {
657 case CHECK_NONE:
658 return 1;
659 case CHECK_SURROUND:
660 return as->ext_id & AC97_EXT_AUDIO_SDAC;
661 case CHECK_CENTER:
662 return as->ext_id & AC97_EXT_AUDIO_CDAC;
663 case CHECK_LFE:
664 return as->ext_id & AC97_EXT_AUDIO_LDAC;
665 case CHECK_SPDIF:
666 return as->ext_id & AC97_EXT_AUDIO_SPDIF;
667 case CHECK_HEADPHONES:
668 return as->caps & AC97_CAPS_HEADPHONES;
669 case CHECK_TONE:
670 return as->caps & AC97_CAPS_TONECTRL;
671 case CHECK_MIC:
672 return as->caps & AC97_CAPS_MICIN;
673 case CHECK_LOUDNESS:
674 return as->caps & AC97_CAPS_LOUDNESS;
675 case CHECK_3D:
676 return AC97_CAPS_ENHANCEMENT(as->caps) != 0;
677 default:
678 printf("%s: internal error: feature=%d\n", __func__, check);
679 return 0;
680 }
681 }
682
683 void
684 ac97_setup_source_info(struct ac97_softc *as)
685 {
686 struct ac97_source_info *si, *si2;
687 int idx, ouridx;
688
689 for (idx = 0, ouridx = 0; idx < nitems(source_info); idx++) {
690 si = &as->source_info[ouridx];
691
692 if (!ac97_check_capability(as, source_info[idx].req_feature))
693 continue;
694
695 bcopy(&source_info[idx], si, sizeof(*si));
696
697 switch (si->type) {
698 case AUDIO_MIXER_CLASS:
699 si->mixer_class = ouridx;
700 ouridx++;
701 break;
702 case AUDIO_MIXER_VALUE:
703 /* Todo - Test to see if it works */
704 ouridx++;
705
706 /* Add an entry for mute, if necessary */
707 if (si->mute) {
708 si = &as->source_info[ouridx];
709 bcopy(&source_info[idx], si, sizeof(*si));
710 si->qualifier = AudioNmute;
711 si->type = AUDIO_MIXER_ENUM;
712 si->info = &ac97_on_off;
713 si->info_size = sizeof(ac97_on_off);
714 si->bits = 1;
715 si->ofs = 15;
716 si->mute = 0;
717 si->polarity = 0;
718 ouridx++;
719 }
720 break;
721 case AUDIO_MIXER_ENUM:
722 /* Todo - Test to see if it works */
723 ouridx++;
724 break;
725 default:
726 printf ("ac97: shouldn't get here\n");
727 break;
728 }
729 }
730
731 as->num_source_info = ouridx;
732
733 for (idx = 0; idx < as->num_source_info; idx++) {
734 int idx2, previdx;
735
736 si = &as->source_info[idx];
737
738 /* Find mixer class */
739 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
740 si2 = &as->source_info[idx2];
741
742 if (si2->type == AUDIO_MIXER_CLASS &&
743 ac97_str_equal(si->class, si2->class)) {
744 si->mixer_class = idx2;
745 }
746 }
747
748
749 /* Setup prev and next pointers */
750 if (si->prev != 0 || si->qualifier)
751 continue;
752
753 si->prev = AUDIO_MIXER_LAST;
754 previdx = idx;
755
756 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
757 if (idx2 == idx)
758 continue;
759
760 si2 = &as->source_info[idx2];
761
762 if (!si2->prev &&
763 ac97_str_equal(si->class, si2->class) &&
764 ac97_str_equal(si->device, si2->device)) {
765 as->source_info[previdx].next = idx2;
766 as->source_info[idx2].prev = previdx;
767
768 previdx = idx2;
769 }
770 }
771
772 as->source_info[previdx].next = AUDIO_MIXER_LAST;
773 }
774 }
775
776 int
777 ac97_attach(struct ac97_host_if *host_if)
778 {
779 struct ac97_softc *as;
780 u_int16_t id1, id2, val;
781 u_int32_t id;
782 u_int16_t extstat, rate;
783 mixer_ctrl_t ctl;
784 int error, i;
785 void (*initfunc)(struct ac97_softc *, int);
786
787 initfunc = NULL;
788
789 if (!(as = malloc(sizeof(*as), M_DEVBUF, M_NOWAIT | M_ZERO)))
790 return (ENOMEM);
791
792 as->codec_if.as = as;
793 as->codec_if.vtbl = &ac97civ;
794 as->host_if = host_if;
795
796 if ((error = host_if->attach(host_if->arg, &as->codec_if))) {
797 free(as, M_DEVBUF, sizeof(*as));
798 return (error);
799 }
800
801 host_if->reset(host_if->arg);
802 DELAY(1000);
803
804 host_if->write(host_if->arg, AC97_REG_POWER, 0);
805 host_if->write(host_if->arg, AC97_REG_RESET, 0);
806 DELAY(10000);
807
808 if (host_if->flags)
809 as->host_flags = host_if->flags(host_if->arg);
810
811 ac97_setup_defaults(as);
812 ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
813 ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
814 ac97_read(as, AC97_REG_RESET, &as->caps);
815
816 id = (id1 << 16) | id2;
817 if (id) {
818 register const struct ac97_vendorid *vendor;
819 register const struct ac97_codecid *codec;
820
821 printf("ac97: codec id 0x%08x", id);
822 for (vendor = &ac97_vendors[sizeof(ac97_vendors) /
823 sizeof(ac97_vendors[0]) - 1];
824 vendor >= ac97_vendors; vendor--) {
825 if (vendor->id == (id & AC97_VENDOR_ID_MASK)) {
826 printf(" (%s", vendor->name);
827 for (codec = &vendor->codecs[vendor->num-1];
828 codec >= vendor->codecs; codec--) {
829 if (codec->id == (id & codec->mask))
830 break;
831 }
832 if (codec >= vendor->codecs && codec->mask) {
833 printf(" %s", codec->name);
834 initfunc = codec->init;
835 } else
836 printf(" <%02x>", id & 0xff);
837 if (codec >= vendor->codecs && codec->rev)
838 printf(" rev %d", id & codec->rev);
839 printf(")");
840 break;
841 }
842 }
843 printf("\n");
844 } else
845 printf("ac97: codec id not read\n");
846
847 if (as->caps) {
848 printf("ac97: codec features ");
849 for (i = 0; i < 10; i++) {
850 if (as->caps & (1 << i))
851 printf("%s, ", ac97feature[i]);
852 }
853 printf("%s\n",
854 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]);
855 }
856
857
858 as->ac97_clock = AC97_STANDARD_CLOCK;
859 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
860 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
861 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM
862 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC
863 | AC97_EXT_AUDIO_LDAC)) {
864
865 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
866 extstat &= ~AC97_EXT_AUDIO_DRA;
867
868 if (as->ext_id & AC97_EXT_AUDIO_VRM)
869 extstat |= AC97_EXT_AUDIO_VRM;
870
871 if (as->ext_id & AC97_EXT_AUDIO_LDAC)
872 extstat |= AC97_EXT_AUDIO_LDAC;
873 if (as->ext_id & AC97_EXT_AUDIO_SDAC)
874 extstat |= AC97_EXT_AUDIO_SDAC;
875 if (as->ext_id & AC97_EXT_AUDIO_CDAC)
876 extstat |= AC97_EXT_AUDIO_CDAC;
877 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
878 /* XXX S/PDIF gets same data as DAC?
879 * maybe this should be settable?
880 * default is SPSAAB (10/11) on AD1980 and ALC codecs.
881 */
882 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK;
883 extstat |= AC97_EXT_AUDIO_SPSA34;
884 ac97_read(as, AC97_REG_SPDIF_CTRL, &val);
885 val = (val & ~AC97_SPDIF_SPSR_MASK) |
886 AC97_SPDIF_SPSR_48K;
887 ac97_write(as, AC97_REG_SPDIF_CTRL, val);
888 }
889 if (as->ext_id & AC97_EXT_AUDIO_VRA)
890 extstat |= AC97_EXT_AUDIO_VRA;
891 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
892 if (as->ext_id & AC97_EXT_AUDIO_VRA) {
893 /* VRA should be enabled. */
894 /* so it claims to do variable rate, let's make sure */
895 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE, 44100);
896 ac97_read(as, AC97_REG_PCM_FRONT_DAC_RATE, &rate);
897 if (rate != 44100) {
898 /* We can't believe ext_id */
899 as->ext_id = 0;
900 }
901 /* restore the default value */
902 ac97_write(as, AC97_REG_PCM_FRONT_DAC_RATE,
903 AC97_SINGLE_RATE);
904 }
905 }
906
907 ac97_setup_source_info(as);
908
909 DELAY(900 * 1000);
910
911 /* use initfunc for specific device */
912 as->codec_if.initfunc = initfunc;
913 if (initfunc != NULL)
914 initfunc(as, 0);
915
916 /* Just enable the DAC and master volumes by default */
917 bzero(&ctl, sizeof(ctl));
918
919 ctl.type = AUDIO_MIXER_ENUM;
920 ctl.un.ord = 0; /* off */
921 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
922 AudioNmaster, AudioNmute);
923 ac97_mixer_set_port(&as->codec_if, &ctl);
924
925 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs,
926 AudioNdac, AudioNmute);
927 ac97_mixer_set_port(&as->codec_if, &ctl);
928
929 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
930 AudioNvolume, AudioNmute);
931 ac97_mixer_set_port(&as->codec_if, &ctl);
932
933 ctl.type = AUDIO_MIXER_ENUM;
934 ctl.un.ord = 0;
935 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
936 AudioNsource, NULL);
937 ac97_mixer_set_port(&as->codec_if, &ctl);
938
939 return (0);
940 }
941
942 int
943 ac97_resume(struct ac97_host_if *host_if, struct ac97_codec_if *codec_if)
944 {
945 struct ac97_softc *as = codec_if->as;
946 u_int16_t val, extstat;
947
948 host_if->reset(host_if->arg);
949 DELAY(1000);
950
951 host_if->write(host_if->arg, AC97_REG_POWER, 0);
952 host_if->write(host_if->arg, AC97_REG_RESET, 0);
953 DELAY(10000);
954
955 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
956 | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM
957 | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC
958 | AC97_EXT_AUDIO_LDAC)) {
959
960 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat);
961 extstat &= ~AC97_EXT_AUDIO_DRA;
962
963 if (as->ext_id & AC97_EXT_AUDIO_VRM)
964 extstat |= AC97_EXT_AUDIO_VRM;
965
966 if (as->ext_id & AC97_EXT_AUDIO_LDAC)
967 extstat |= AC97_EXT_AUDIO_LDAC;
968 if (as->ext_id & AC97_EXT_AUDIO_SDAC)
969 extstat |= AC97_EXT_AUDIO_SDAC;
970 if (as->ext_id & AC97_EXT_AUDIO_CDAC)
971 extstat |= AC97_EXT_AUDIO_CDAC;
972
973 if (as->ext_id & AC97_EXT_AUDIO_SPDIF) {
974 extstat &= ~AC97_EXT_AUDIO_SPSA_MASK;
975 extstat |= AC97_EXT_AUDIO_SPSA34;
976 ac97_read(as, AC97_REG_SPDIF_CTRL, &val);
977 val = (val & ~AC97_SPDIF_SPSR_MASK) |
978 AC97_SPDIF_SPSR_48K;
979 ac97_write(as, AC97_REG_SPDIF_CTRL, val);
980 }
981 if (as->ext_id & AC97_EXT_AUDIO_VRA)
982 extstat |= AC97_EXT_AUDIO_VRA;
983 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat);
984 }
985
986 /* use initfunc for specific device */
987 if (as->codec_if.initfunc != NULL)
988 as->codec_if.initfunc(as, 1);
989
990 return (0);
991 }
992
993 void
994 ac97_lock(struct ac97_codec_if *codec_if)
995 {
996 struct ac97_softc *as = (struct ac97_softc *)codec_if;
997 as->lock_counter++;
998 }
999
1000 void
1001 ac97_unlock(struct ac97_codec_if *codec_if)
1002 {
1003 struct ac97_softc *as = (struct ac97_softc *)codec_if;
1004 as->lock_counter--;
1005 }
1006
1007 int
1008 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
1009 {
1010 struct ac97_softc *as = (struct ac97_softc *)codec_if;
1011
1012 if (dip->index < as->num_source_info && dip->index >= 0) {
1013 struct ac97_source_info *si = &as->source_info[dip->index];
1014 const char *name;
1015
1016 dip->type = si->type;
1017 dip->mixer_class = si->mixer_class;
1018 dip->prev = si->prev;
1019 dip->next = si->next;
1020
1021 if (si->qualifier)
1022 name = si->qualifier;
1023 else if (si->device)
1024 name = si->device;
1025 else if (si->class)
1026 name = si->class;
1027 else
1028 name = NULL;
1029
1030 if (name)
1031 strlcpy(dip->label.name, name, sizeof dip->label.name);
1032
1033 bcopy(si->info, &dip->un, si->info_size);
1034
1035 /* Set the delta for volume sources */
1036 if (dip->type == AUDIO_MIXER_VALUE)
1037 dip->un.v.delta = 1 << (8 - si->bits);
1038
1039 return (0);
1040 }
1041
1042 return (ENXIO);
1043 }
1044
1045 int
1046 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1047 {
1048 struct ac97_softc *as = (struct ac97_softc *)codec_if;
1049 struct ac97_source_info *si;
1050 u_int16_t mask;
1051 u_int16_t val, newval;
1052 int error, spdif;
1053
1054 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1055 return (EINVAL);
1056
1057 si = &as->source_info[cp->dev];
1058
1059 if (cp->type == AUDIO_MIXER_CLASS || cp->type != si->type)
1060 return (EINVAL);
1061
1062 spdif = si->req_feature == CHECK_SPDIF &&
1063 si->reg == AC97_REG_EXT_AUDIO_CTRL;
1064 if (spdif && as->lock_counter >= 0)
1065 return EBUSY;
1066
1067 ac97_read(as, si->reg, &val);
1068
1069 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1070
1071 mask = (1 << si->bits) - 1;
1072
1073 switch (cp->type) {
1074 case AUDIO_MIXER_ENUM:
1075 if (cp->un.ord > mask || cp->un.ord < 0)
1076 return (EINVAL);
1077
1078 newval = (cp->un.ord << si->ofs);
1079 if (si->reg == AC97_REG_RECORD_SELECT) {
1080 newval |= (newval << (8 + si->ofs));
1081 mask |= (mask << 8);
1082 mask = mask << si->ofs;
1083 } else if (si->reg == AC97_REG_SURR_MASTER) {
1084 newval = cp->un.ord ? 0x8080 : 0x0000;
1085 mask = 0x8080;
1086 } else
1087 mask = mask << si->ofs;
1088
1089 if (si->mute) {
1090 newval |= newval << 8;
1091 mask |= mask << 8;
1092 }
1093
1094 break;
1095 case AUDIO_MIXER_VALUE:
1096 {
1097 const struct audio_mixer_value *value = si->info;
1098 u_int16_t l, r;
1099
1100 if (cp->un.value.num_channels <= 0 ||
1101 cp->un.value.num_channels > value->num_channels)
1102 return (EINVAL);
1103
1104 if (cp->un.value.num_channels == 1) {
1105 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1106 } else {
1107 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1108 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1109 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1110 } else {
1111 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1112 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1113 }
1114 }
1115
1116 if (!si->polarity) {
1117 l = 255 - l;
1118 r = 255 - r;
1119 }
1120
1121 l >>= 8 - si->bits;
1122 r >>= 8 - si->bits;
1123
1124 newval = ((l & mask) << si->ofs);
1125 if (value->num_channels == 2) {
1126 newval |= ((r & mask) << (si->ofs + 8));
1127 mask |= (mask << 8);
1128 }
1129 mask = mask << si->ofs;
1130 break;
1131 }
1132 default:
1133 return (EINVAL);
1134 }
1135
1136 error = ac97_write(as, si->reg, (val & ~mask) | newval);
1137 if (error)
1138 return (error);
1139
1140 if (spdif && as->host_if->spdif_event != NULL)
1141 as->host_if->spdif_event(as->host_if->arg, cp->un.ord);
1142
1143 return (0);
1144 }
1145
1146
1147 int
1148 ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate)
1149 {
1150 struct ac97_softc *as;
1151 u_long value;
1152 u_int16_t ext_stat;
1153 u_int16_t actual;
1154 u_int16_t power;
1155 u_int16_t power_bit;
1156
1157 as = (struct ac97_softc *)codec_if;
1158
1159 if ((target == AC97_REG_PCM_SURR_DAC_RATE) &&
1160 !(as->ext_id & AC97_EXT_AUDIO_SDAC))
1161 return 0;
1162 if ((target == AC97_REG_PCM_LFE_DAC_RATE) &&
1163 !(as->ext_id & AC97_EXT_AUDIO_LDAC))
1164 return 0;
1165 if (target == AC97_REG_PCM_MIC_ADC_RATE) {
1166 if (!(as->ext_id & AC97_EXT_AUDIO_VRM)) {
1167 *rate = AC97_SINGLE_RATE;
1168 return 0;
1169 }
1170 } else {
1171 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1172 *rate = AC97_SINGLE_RATE;
1173 return 0;
1174 }
1175 }
1176 if (as->ac97_clock == 0)
1177 as->ac97_clock = AC97_STANDARD_CLOCK;
1178 value = *rate * AC97_STANDARD_CLOCK / as->ac97_clock;
1179 ext_stat = 0;
1180 /*
1181 * PCM_FRONT_DAC_RATE/PCM_SURR_DAC_RATE/PCM_LFE_DAC_RATE
1182 * Check VRA, DRA
1183 * PCM_LR_ADC_RATE
1184 * Check VRA
1185 * PCM_MIC_ADC_RATE
1186 * Check VRM
1187 */
1188 switch (target) {
1189 case AC97_REG_PCM_FRONT_DAC_RATE:
1190 case AC97_REG_PCM_SURR_DAC_RATE:
1191 case AC97_REG_PCM_LFE_DAC_RATE:
1192 power_bit = AC97_POWER_OUT;
1193 if (as->ext_id & AC97_EXT_AUDIO_DRA) {
1194 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &ext_stat);
1195 if (value > 0x1ffff) {
1196 return EINVAL;
1197 } else if (value > 0xffff) {
1198 /* Enable DRA */
1199 ext_stat |= AC97_EXT_AUDIO_DRA;
1200 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1201 value /= 2;
1202 } else {
1203 /* Disable DRA */
1204 ext_stat &= ~AC97_EXT_AUDIO_DRA;
1205 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, ext_stat);
1206 }
1207 } else {
1208 if (value > 0xffff)
1209 return EINVAL;
1210 }
1211 break;
1212 case AC97_REG_PCM_LR_ADC_RATE:
1213 power_bit = AC97_POWER_IN;
1214 if (value > 0xffff)
1215 return EINVAL;
1216 break;
1217 case AC97_REG_PCM_MIC_ADC_RATE:
1218 power_bit = AC97_POWER_IN;
1219 if (value > 0xffff)
1220 return EINVAL;
1221 break;
1222 default:
1223 printf("%s: Unknown register: 0x%x\n", __func__, target);
1224 return EINVAL;
1225 }
1226
1227 ac97_read(as, AC97_REG_POWER, &power);
1228 ac97_write(as, AC97_REG_POWER, power | power_bit);
1229
1230 ac97_write(as, target, (u_int16_t)value);
1231 ac97_read(as, target, &actual);
1232 actual = (u_int32_t)actual * as->ac97_clock / AC97_STANDARD_CLOCK;
1233
1234 ac97_write(as, AC97_REG_POWER, power);
1235 if (ext_stat & AC97_EXT_AUDIO_DRA) {
1236 *rate = actual * 2;
1237 } else {
1238 *rate = actual;
1239 }
1240 return 0;
1241 }
1242
1243 void
1244 ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock)
1245 {
1246 struct ac97_softc *as;
1247
1248 as = (struct ac97_softc *)codec_if;
1249 as->ac97_clock = clock;
1250 }
1251
1252 u_int16_t
1253 ac97_get_extcaps(struct ac97_codec_if *codec_if)
1254 {
1255 struct ac97_softc *as;
1256
1257 as = (struct ac97_softc *)codec_if;
1258 return as->ext_id;
1259 }
1260
1261 int
1262 ac97_add_port(struct ac97_softc *as, struct ac97_source_info *src)
1263 {
1264 struct ac97_source_info *si;
1265 int ouridx, idx;
1266
1267 if (as->num_source_info >= MAX_SOURCES) {
1268 printf("%s: internal error: increase MAX_SOURCES in %s\n",
1269 __func__, __FILE__);
1270 return -1;
1271 }
1272 if (!ac97_check_capability(as, src->req_feature))
1273 return -1;
1274 ouridx = as->num_source_info;
1275 si = &as->source_info[ouridx];
1276 memcpy(si, src, sizeof(*si));
1277
1278 switch (si->type) {
1279 case AUDIO_MIXER_CLASS:
1280 case AUDIO_MIXER_VALUE:
1281 printf("%s: adding class/value is not supported yet.\n",
1282 __func__);
1283 return -1;
1284 case AUDIO_MIXER_ENUM:
1285 break;
1286 default:
1287 printf("%s: unknown type: %d\n", __func__, si->type);
1288 return -1;
1289 }
1290 as->num_source_info++;
1291
1292 si->mixer_class = ac97_get_portnum_by_name(&as->codec_if, si->class,
1293 NULL, NULL);
1294 /* Find the root of the device */
1295 idx = ac97_get_portnum_by_name(&as->codec_if, si->class,
1296 si->device, NULL);
1297 /* Find the last item */
1298 while (as->source_info[idx].next != AUDIO_MIXER_LAST)
1299 idx = as->source_info[idx].next;
1300 /* Append */
1301 as->source_info[idx].next = ouridx;
1302 si->prev = idx;
1303 si->next = AUDIO_MIXER_LAST;
1304
1305 return 0;
1306 }
1307
1308 int
1309 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, char *class,
1310 char *device, char *qualifier)
1311 {
1312 struct ac97_softc *as = (struct ac97_softc *)codec_if;
1313 int idx;
1314
1315 for (idx = 0; idx < as->num_source_info; idx++) {
1316 struct ac97_source_info *si = &as->source_info[idx];
1317 if (ac97_str_equal(class, si->class) &&
1318 ac97_str_equal(device, si->device) &&
1319 ac97_str_equal(qualifier, si->qualifier))
1320 return (idx);
1321 }
1322
1323 return (-1);
1324 }
1325
1326 int
1327 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
1328 {
1329 struct ac97_softc *as = (struct ac97_softc *)codec_if;
1330 struct ac97_source_info *si;
1331 u_int16_t mask;
1332 u_int16_t val;
1333
1334 if (cp->dev < 0 || cp->dev >= as->num_source_info)
1335 return (EINVAL);
1336
1337 si = &as->source_info[cp->dev];
1338
1339 if (cp->type != si->type)
1340 return (EINVAL);
1341
1342 ac97_read(as, si->reg, &val);
1343
1344 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
1345
1346 mask = (1 << si->bits) - 1;
1347
1348 switch (cp->type) {
1349 case AUDIO_MIXER_ENUM:
1350 cp->un.ord = (val >> si->ofs) & mask;
1351 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs,
1352 mask, cp->un.ord));
1353 break;
1354 case AUDIO_MIXER_VALUE:
1355 {
1356 const struct audio_mixer_value *value = si->info;
1357 u_int16_t l, r;
1358
1359 if ((cp->un.value.num_channels <= 0) ||
1360 (cp->un.value.num_channels > value->num_channels))
1361 return (EINVAL);
1362
1363 if (value->num_channels == 1)
1364 l = r = (val >> si->ofs) & mask;
1365 else {
1366 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1367 l = (val >> si->ofs) & mask;
1368 r = (val >> (si->ofs + 8)) & mask;
1369 } else {
1370 r = (val >> si->ofs) & mask;
1371 l = (val >> (si->ofs + 8)) & mask;
1372 }
1373 }
1374
1375 l <<= 8 - si->bits;
1376 r <<= 8 - si->bits;
1377 if (!si->polarity) {
1378 l = 255 - l;
1379 r = 255 - r;
1380 }
1381
1382 /*
1383 * The EAP driver averages l and r for stereo
1384 * channels that are requested in MONO mode. Does this
1385 * make sense?
1386 */
1387 if (cp->un.value.num_channels == 1) {
1388 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1389 } else if (cp->un.value.num_channels == 2) {
1390 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1391 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1392 }
1393
1394 break;
1395 }
1396 default:
1397 return (EINVAL);
1398 }
1399
1400 return (0);
1401 }
1402
1403
1404 /*
1405 * Codec-dependent initialization
1406 */
1407
1408 void
1409 ac97_ad1885_init(struct ac97_softc *as, int resuming)
1410 {
1411 int i;
1412
1413 if (resuming)
1414 return;
1415
1416 for (i = 0; i < as->num_source_info; i++) {
1417 if (as->source_info[i].reg == AC97_REG_HEADPHONE_VOLUME)
1418 as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
1419 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
1420 as->source_info[i].reg = AC97_REG_HEADPHONE_VOLUME;
1421 }
1422 }
1423
1424 #define AC97_AD1886_JACK_SENSE 0x72
1425
1426 void
1427 ac97_ad1886_init(struct ac97_softc *as, int resuming)
1428 {
1429 ac97_write(as, AC97_AD1886_JACK_SENSE, 0x0010);
1430 }
1431
1432 void
1433 ac97_ad198x_init(struct ac97_softc *as, int resuming)
1434 {
1435 int i;
1436 u_int16_t misc;
1437
1438 ac97_read(as, AC97_AD_REG_MISC, &misc);
1439 ac97_write(as, AC97_AD_REG_MISC,
1440 misc|AC97_AD_MISC_HPSEL|AC97_AD_MISC_LOSEL);
1441
1442 if (resuming)
1443 return;
1444
1445 for (i = 0; i < as->num_source_info; i++) {
1446 if (as->source_info[i].reg == AC97_REG_SURR_MASTER)
1447 as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
1448 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME)
1449 as->source_info[i].reg = AC97_REG_SURR_MASTER;
1450 }
1451 }
1452
1453 void
1454 ac97_alc650_init(struct ac97_softc *as, int resuming)
1455 {
1456 u_int16_t misc;
1457
1458 ac97_read(as, AC97_ALC650_REG_MISC, &misc);
1459 if (as->host_flags & AC97_HOST_ALC650_PIN47_IS_EAPD)
1460 misc &= ~AC97_ALC650_MISC_PIN47;
1461 misc &= ~AC97_ALC650_MISC_VREFDIS;
1462 ac97_write(as, AC97_ALC650_REG_MISC, misc);
1463
1464 if (resuming)
1465 return;
1466
1467 struct ac97_source_info sources[3] = {
1468 { AudioCoutputs, AudioNsurround, "lineinjack",
1469 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1470 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL,
1471 0x0000, 1, 9, 0, 0, CHECK_SURROUND },
1472 { AudioCoutputs, AudioNcenter, "micjack",
1473 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1474 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL,
1475 0x0000, 1, 10, 0, 0, CHECK_CENTER },
1476 { AudioCoutputs, AudioNlfe, "micjack",
1477 AUDIO_MIXER_ENUM, WRAP(ac97_on_off),
1478 AC97_ALC650_REG_MULTI_CHANNEL_CONTROL,
1479 0x0000, 1, 10, 0, 0, CHECK_LFE }};
1480
1481 ac97_add_port(as, &sources[0]);
1482 ac97_add_port(as, &sources[1]);
1483 ac97_add_port(as, &sources[2]);
1484 }
1485
1486 void
1487 ac97_cx20468_init(struct ac97_softc *as, int resuming)
1488 {
1489 u_int16_t misc;
1490
1491 ac97_read(as, AC97_CX_REG_MISC, &misc);
1492 ac97_write(as, AC97_CX_REG_MISC, misc &
1493 ~(AC97_CX_SPDIFEN | AC97_CX_COPYRIGHT | AC97_CX_MASK));
1494 }
1495
1496 void
1497 ac97_vt1616_init(struct ac97_softc *as, int resuming)
1498 {
1499 u_int16_t reg;
1500
1501 if (as->host_flags & AC97_HOST_VT1616_DYNEX) {
1502 ac97_read(as, AC97_VT_REG_TEST, ®);
1503
1504 /* disable 'hp' mixer controls controlling the surround pins */
1505 reg &= ~(AC97_VT_LVL);
1506
1507 /* disable downmixing */
1508 reg &= ~(AC97_VT_LCTF | AC97_VT_STF);
1509
1510 /* enable DC offset removal */
1511 reg |= AC97_VT_BPDC;
1512
1513 ac97_write(as, AC97_VT_REG_TEST, reg);
1514 }
1515 }
Cache object: b44865c75ba6590dc9219f2ee5177ae4
|