This source file includes following definitions.
- ac97_read
- ac97_write
- ac97_setup_defaults
- ac97_restore_shadow
- ac97_str_equal
- ac97_setup_source_info
- ac97_attach
- ac97_query_devinfo
- ac97_mixer_set_port
- ac97_get_portnum_by_name
- ac97_mixer_get_port
- ac97_set_rate
- ac97_ad1886_init
- ac97_ad198x_init
- ac97_alc655_init
- ac97_cx20468_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/malloc.h>
67 #include <sys/device.h>
68
69 #include <sys/audioio.h>
70 #include <dev/audio_if.h>
71 #include <dev/ic/ac97.h>
72
73 const struct audio_mixer_enum ac97_on_off = {
74 2,
75 { { { AudioNoff } , 0 },
76 { { AudioNon } , 1 } }
77 };
78
79 const struct audio_mixer_enum ac97_mic_select = {
80 2,
81 { { { AudioNmicrophone "0" }, 0 },
82 { { AudioNmicrophone "1" }, 1 } }
83 };
84
85 const struct audio_mixer_enum ac97_mono_select = {
86 2,
87 { { { AudioNmixerout }, 0 },
88 { { AudioNmicrophone }, 1 } }
89 };
90
91 const struct audio_mixer_enum ac97_source = {
92 8,
93 { { { AudioNmicrophone } , 0 },
94 { { AudioNcd }, 1 },
95 { { "video" }, 2 },
96 { { AudioNaux }, 3 },
97 { { AudioNline }, 4 },
98 { { AudioNmixerout }, 5 },
99 { { AudioNmixerout AudioNmono }, 6 },
100 { { "phone" }, 7 }}
101 };
102
103
104
105
106
107
108 const struct audio_mixer_value ac97_volume_stereo = {
109 { AudioNvolume },
110 2
111 };
112
113 const struct audio_mixer_value ac97_volume_mono = {
114 { AudioNvolume },
115 1
116 };
117
118 #define WRAP(a) &a, sizeof(a)
119
120 const struct ac97_source_info {
121 char *class;
122 char *device;
123 char *qualifier;
124 int type;
125
126 const void *info;
127 int16_t info_size;
128
129 u_int8_t reg;
130 u_int8_t bits:3;
131 u_int8_t ofs:4;
132 u_int8_t mute:1;
133 u_int8_t polarity:1;
134 u_int16_t default_value;
135
136 int16_t prev;
137 int16_t next;
138 int16_t mixer_class;
139 } source_info[] = {
140 {
141 AudioCinputs, NULL, NULL, AUDIO_MIXER_CLASS,
142 }, {
143 AudioCoutputs, NULL, NULL, AUDIO_MIXER_CLASS,
144 }, {
145 AudioCrecord, NULL, NULL, AUDIO_MIXER_CLASS,
146 }, {
147
148 AudioCoutputs, AudioNmaster, NULL, AUDIO_MIXER_VALUE,
149 WRAP(ac97_volume_stereo),
150 AC97_REG_MASTER_VOLUME, 5, 0, 1, 0, 0x8000
151 }, {
152
153 AudioCoutputs, AudioNmono, NULL, AUDIO_MIXER_VALUE,
154 WRAP(ac97_volume_mono),
155 AC97_REG_MASTER_VOLUME_MONO, 6, 0, 1, 0, 0x8000
156 }, {
157 AudioCoutputs, AudioNmono, AudioNsource, AUDIO_MIXER_ENUM,
158 WRAP(ac97_mono_select),
159 AC97_REG_GP, 1, 9, 0, 0, 0x0000
160 }, {
161
162 AudioCoutputs, AudioNheadphone, NULL, AUDIO_MIXER_VALUE,
163 WRAP(ac97_volume_stereo),
164 AC97_REG_HEADPHONE_VOLUME, 6, 0, 1, 0, 0x8000
165 }, {
166 AudioCoutputs, AudioNbass, NULL, AUDIO_MIXER_VALUE,
167 WRAP(ac97_volume_mono),
168 AC97_REG_MASTER_TONE, 4, 8, 0, 0, 0x0f0f
169 }, {
170 AudioCoutputs, AudioNtreble, NULL, AUDIO_MIXER_VALUE,
171 WRAP(ac97_volume_mono),
172 AC97_REG_MASTER_TONE, 4, 0, 0, 0, 0x0f0f
173 }, {
174
175 AudioCinputs, AudioNspeaker, NULL, AUDIO_MIXER_VALUE,
176 WRAP(ac97_volume_mono),
177 AC97_REG_PCBEEP_VOLUME, 4, 1, 1, 0, 0x0000
178 }, {
179
180 AudioCinputs, "phone", NULL, AUDIO_MIXER_VALUE,
181 WRAP(ac97_volume_mono),
182 AC97_REG_PHONE_VOLUME, 5, 0, 1, 0, 0x8008
183 }, {
184
185 AudioCinputs, AudioNmicrophone, NULL, AUDIO_MIXER_VALUE,
186 WRAP(ac97_volume_mono),
187 AC97_REG_MIC_VOLUME, 5, 0, 1, 0, 0x8008
188 }, {
189 AudioCinputs, AudioNmicrophone, AudioNpreamp, AUDIO_MIXER_ENUM,
190 WRAP(ac97_on_off),
191 AC97_REG_MIC_VOLUME, 1, 6, 0, 0, 0x8008
192 }, {
193 AudioCinputs, AudioNmicrophone, AudioNsource, AUDIO_MIXER_ENUM,
194 WRAP(ac97_mic_select),
195 AC97_REG_GP, 1, 8, 0, 0x0000
196 }, {
197
198 AudioCinputs, AudioNline, NULL, AUDIO_MIXER_VALUE,
199 WRAP(ac97_volume_stereo),
200 AC97_REG_LINEIN_VOLUME, 5, 0, 1, 0, 0x8808
201 }, {
202
203 AudioCinputs, AudioNcd, NULL, AUDIO_MIXER_VALUE,
204 WRAP(ac97_volume_stereo),
205 AC97_REG_CD_VOLUME, 5, 0, 1, 0, 0x8808
206 }, {
207
208 AudioCinputs, "video", NULL, AUDIO_MIXER_VALUE,
209 WRAP(ac97_volume_stereo),
210 AC97_REG_VIDEO_VOLUME, 5, 0, 1, 0, 0x8808
211 }, {
212
213 AudioCinputs, AudioNaux, NULL, AUDIO_MIXER_VALUE,
214 WRAP(ac97_volume_stereo),
215 AC97_REG_AUX_VOLUME, 5, 0, 1, 0, 0x8808
216 }, {
217
218 AudioCinputs, AudioNdac, NULL, AUDIO_MIXER_VALUE,
219 WRAP(ac97_volume_stereo),
220 AC97_REG_PCMOUT_VOLUME, 5, 0, 1, 0, 0x8808
221 }, {
222
223 AudioCrecord, AudioNsource, NULL, AUDIO_MIXER_ENUM,
224 WRAP(ac97_source),
225 AC97_REG_RECORD_SELECT, 3, 0, 0, 0, 0x0000
226 }, {
227
228 AudioCrecord, AudioNvolume, NULL, AUDIO_MIXER_VALUE,
229 WRAP(ac97_volume_stereo),
230 AC97_REG_RECORD_GAIN, 4, 0, 1, 0, 0x8000
231 }, {
232
233 AudioCrecord, AudioNmicrophone, NULL, AUDIO_MIXER_VALUE,
234 WRAP(ac97_volume_mono),
235 AC97_REG_RECORD_GAIN_MIC, 4, 0, 1, 1, 0x8000
236 }, {
237
238 AudioCoutputs, AudioNloudness, NULL, AUDIO_MIXER_ENUM,
239 WRAP(ac97_on_off),
240 AC97_REG_GP, 1, 12, 0, 0, 0x0000
241 }, {
242 AudioCoutputs, AudioNspatial, NULL, AUDIO_MIXER_ENUM,
243 WRAP(ac97_on_off),
244 AC97_REG_GP, 1, 13, 0, 0, 0x0000
245 }, {
246 AudioCoutputs, AudioNspatial, AudioNcenter,AUDIO_MIXER_VALUE,
247 WRAP(ac97_volume_mono),
248 AC97_REG_3D_CONTROL, 4, 8, 0, 1, 0x0000
249 }, {
250 AudioCoutputs, AudioNspatial, AudioNdepth, AUDIO_MIXER_VALUE,
251 WRAP(ac97_volume_mono),
252 AC97_REG_3D_CONTROL, 4, 0, 0, 1, 0x0000
253 }, {
254
255 AudioCoutputs, AudioNsurround, NULL, AUDIO_MIXER_VALUE,
256 WRAP(ac97_volume_stereo),
257 AC97_REG_SURROUND_VOLUME, 6, 0, 1, 0, 0x8080
258 }, {
259
260 AudioCoutputs, AudioNcenter, NULL, AUDIO_MIXER_VALUE,
261 WRAP(ac97_volume_mono),
262 AC97_REG_CENTER_LFE_VOLUME, 6, 0, 1, 0, 0x8080
263 }, {
264
265 AudioCoutputs, AudioNlfe, NULL, AUDIO_MIXER_VALUE,
266 WRAP(ac97_volume_mono),
267 AC97_REG_CENTER_LFE_VOLUME, 6, 8, 1, 0, 0x8080
268 }, {
269
270 AudioCoutputs, AudioNextamp, NULL, AUDIO_MIXER_ENUM,
271 WRAP(ac97_on_off),
272 AC97_REG_POWER, 1, 15, 0, 0, 0x0000
273 }
274
275
276 };
277
278 #define SOURCE_INFO_SIZE (sizeof(source_info)/sizeof(source_info[0]))
279
280
281
282
283
284
285 struct ac97_softc {
286 struct ac97_codec_if codec_if;
287 struct ac97_host_if *host_if;
288 struct ac97_source_info source_info[2 * SOURCE_INFO_SIZE];
289 int num_source_info;
290 enum ac97_host_flags host_flags;
291 u_int16_t caps, ext_id;
292 u_int16_t shadow_reg[128];
293 };
294
295 int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *);
296 int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *);
297 int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *);
298 int ac97_get_portnum_by_name(struct ac97_codec_if *, char *, char *,
299 char *);
300 void ac97_restore_shadow(struct ac97_codec_if *);
301
302 void ac97_ad1886_init(struct ac97_softc *);
303 void ac97_ad198x_init(struct ac97_softc *);
304 void ac97_alc655_init(struct ac97_softc *);
305 void ac97_cx20468_init(struct ac97_softc *);
306
307 struct ac97_codec_if_vtbl ac97civ = {
308 ac97_mixer_get_port,
309 ac97_mixer_set_port,
310 ac97_query_devinfo,
311 ac97_get_portnum_by_name,
312 ac97_restore_shadow
313 };
314
315 const struct ac97_codecid {
316 u_int8_t id;
317 u_int8_t mask;
318 u_int8_t rev;
319 u_int8_t shift;
320 char * const name;
321 void (*init)(struct ac97_softc *);
322 } ac97_ad[] = {
323 { 0x03, 0xff, 0, 0, "AD1819" },
324 { 0x40, 0xff, 0, 0, "AD1881" },
325 { 0x48, 0xff, 0, 0, "AD1881A" },
326 { 0x60, 0xff, 0, 0, "AD1885" },
327 { 0x61, 0xff, 0, 0, "AD1886", ac97_ad1886_init },
328 { 0x63, 0xff, 0, 0, "AD1886A" },
329 { 0x68, 0xff, 0, 0, "AD1888", ac97_ad198x_init },
330 { 0x70, 0xff, 0, 0, "AD1980" },
331 { 0x72, 0xff, 0, 0, "AD1981A" },
332 { 0x74, 0xff, 0, 0, "AD1981B" },
333 { 0x75, 0xff, 0, 0, "AD1985", ac97_ad198x_init },
334 }, ac97_ak[] = {
335 { 0x00, 0xfe, 1, 0, "AK4540" },
336 { 0x01, 0xfe, 1, 0, "AK4540" },
337 { 0x02, 0xff, 0, 0, "AK4543" },
338 { 0x05, 0xff, 0, 0, "AK4544" },
339 { 0x06, 0xff, 0, 0, "AK4544A" },
340 { 0x07, 0xff, 0, 0, "AK4545" },
341 }, ac97_av[] = {
342 { 0x10, 0xff, 0, 0, "ALC200" },
343 { 0x20, 0xff, 0, 0, "ALC650" },
344 { 0x21, 0xff, 0, 0, "ALC650D" },
345 { 0x22, 0xff, 0, 0, "ALC650E" },
346 { 0x23, 0xff, 0, 0, "ALC650F" },
347 { 0x30, 0xff, 0, 0, "ALC101" },
348 { 0x40, 0xff, 0, 0, "ALC202" },
349 { 0x50, 0xff, 0, 0, "ALC250" },
350 { 0x52, 0xff, 0, 0, "ALC250A?" },
351 { 0x60, 0xf0, 0xf, 0, "ALC655", ac97_alc655_init },
352 { 0x70, 0xf0, 0xf, 0, "ALC203" },
353 { 0x80, 0xf0, 0xf, 0, "ALC658", ac97_alc655_init },
354 { 0x90, 0xf0, 0xf, 0, "ALC850" },
355 }, ac97_rl[] = {
356 { 0x00, 0xf0, 0xf, 0, "RL5306" },
357 { 0x10, 0xf0, 0xf, 0, "RL5382" },
358 { 0x20, 0xf0, 0xf, 0, "RL5383" },
359 }, ac97_cm[] = {
360 { 0x41, 0xff, 0, 0, "CMI9738" },
361 { 0x61, 0xff, 0, 0, "CMI9739" },
362 { 0x78, 0xff, 0, 0, "CMI9761A" },
363 { 0x82, 0xff, 0, 0, "CMI9761B" },
364 { 0x83, 0xff, 0, 0, "CMI9761A+" },
365 }, ac97_cr[] = {
366 { 0x84, 0xff, 0, 0, "EV1938" },
367 }, ac97_cs[] = {
368 { 0x00, 0xf8, 7, 0, "CS4297" },
369 { 0x10, 0xf8, 7, 0, "CS4297A" },
370 { 0x20, 0xf8, 7, 0, "CS4298" },
371 { 0x28, 0xf8, 7, 0, "CS4294" },
372 { 0x30, 0xf8, 7, 0, "CS4299" },
373 { 0x48, 0xf8, 7, 0, "CS4201" },
374 { 0x58, 0xf8, 7, 0, "CS4205" },
375 { 0x60, 0xf8, 7, 0, "CS4291" },
376 { 0x70, 0xf8, 7, 0, "CS4202" },
377 }, ac97_cx[] = {
378 { 0x21, 0xff, 0, 0, "HSD11246" },
379 { 0x28, 0xf8, 7, 0, "CX20468", ac97_cx20468_init },
380 { 0x30, 0xff, 0, 0, "CXT48", },
381 { 0x42, 0xff, 0, 0, "CXT66", },
382 }, ac97_dt[] = {
383 { 0x00, 0xff, 0, 0, "DT0398" },
384 }, ac97_em[] = {
385 { 0x23, 0xff, 0, 0, "EM28023" },
386 { 0x28, 0xff, 0, 0, "EM28028" },
387 }, ac97_es[] = {
388 { 0x08, 0xff, 0, 0, "ES1921" },
389 }, ac97_is[] = {
390 { 0x00, 0xff, 0, 0, "HMP9701" },
391 }, ac97_ic[] = {
392 { 0x01, 0xff, 0, 0, "ICE1230" },
393 { 0x11, 0xff, 0, 0, "ICE1232" },
394 { 0x14, 0xff, 0, 0, "ICE1232A" },
395 { 0x51, 0xff, 0, 0, "VIA VT1616" },
396 { 0x52, 0xff, 0, 0, "VIA VT1616i" },
397 }, ac97_it[] = {
398 { 0x20, 0xff, 0, 0, "ITE2226E" },
399 { 0x60, 0xff, 0, 0, "ITE2646E" },
400 }, ac97_ns[] = {
401 { 0x00, 0xff, 0, 0, "LM454[03568]" },
402 { 0x31, 0xff, 0, 0, "LM4549" },
403 { 0x40, 0xff, 0, 0, "LM4540" },
404 { 0x43, 0xff, 0, 0, "LM4543" },
405 { 0x46, 0xff, 0, 0, "LM4546A" },
406 { 0x48, 0xff, 0, 0, "LM4548A" },
407 { 0x49, 0xff, 0, 0, "LM4549A" },
408 { 0x50, 0xff, 0, 0, "LM4550" },
409 }, ac97_ps[] = {
410 { 0x01, 0xff, 0, 0, "UCB1510" },
411 { 0x04, 0xff, 0, 0, "UCB1400" },
412 }, ac97_sl[] = {
413 { 0x20, 0xe0, 0, 0, "Si3036/38" },
414 }, ac97_st[] = {
415 { 0x00, 0xff, 0, 0, "STAC9700" },
416 { 0x04, 0xff, 0, 0, "STAC970[135]" },
417 { 0x05, 0xff, 0, 0, "STAC9704" },
418 { 0x08, 0xff, 0, 0, "STAC9708/11" },
419 { 0x09, 0xff, 0, 0, "STAC9721/23" },
420 { 0x44, 0xff, 0, 0, "STAC9744/45" },
421 { 0x50, 0xff, 0, 0, "STAC9750/51" },
422 { 0x52, 0xff, 0, 0, "STAC9752/53" },
423 { 0x56, 0xff, 0, 0, "STAC9756/57" },
424 { 0x58, 0xff, 0, 0, "STAC9758/59" },
425 { 0x60, 0xff, 0, 0, "STAC9760/61" },
426 { 0x62, 0xff, 0, 0, "STAC9762/63" },
427 { 0x66, 0xff, 0, 0, "STAC9766/67" },
428 { 0x84, 0xff, 0, 0, "STAC9784/85" },
429 }, ac97_vi[] = {
430 { 0x61, 0xff, 0, 0, "VT1612A" },
431 }, ac97_tt[] = {
432 { 0x02, 0xff, 0, 0, "TR28022" },
433 { 0x03, 0xff, 0, 0, "TR28023" },
434 { 0x06, 0xff, 0, 0, "TR28026" },
435 { 0x08, 0xff, 0, 0, "TR28028" },
436 { 0x23, 0xff, 0, 0, "TR28602" },
437 }, ac97_ti[] = {
438 { 0x20, 0xff, 0, 0, "TLC320AD9xC" },
439 }, ac97_wb[] = {
440 { 0x01, 0xff, 0, 0, "W83971D" },
441 }, ac97_wo[] = {
442 { 0x00, 0xff, 0, 0, "WM9701A" },
443 { 0x03, 0xff, 0, 0, "WM9704M/Q-0" },
444 { 0x04, 0xff, 0, 0, "WM9704M/Q-1" },
445 { 0x05, 0xff, 0, 0, "WM9705/10" },
446 { 0x09, 0xff, 0, 0, "WM9709" },
447 { 0x12, 0xff, 0, 0, "WM9711/12" },
448 }, ac97_ym[] = {
449 { 0x00, 0xff, 0, 0, "YMF743-S" },
450 { 0x02, 0xff, 0, 0, "YMF752-S" },
451 { 0x03, 0xff, 0, 0, "YMF753-S" },
452 };
453
454 #define cl(n) n, sizeof(n)/sizeof(n[0])
455 const struct ac97_vendorid {
456 u_int32_t id;
457 char * const name;
458 const struct ac97_codecid * const codecs;
459 u_int8_t num;
460 } ac97_vendors[] = {
461 { 0x01408300, "Creative", cl(ac97_cr) },
462 { 0x41445300, "Analog Devices", cl(ac97_ad) },
463 { 0x414b4D00, "Asahi Kasei", cl(ac97_ak) },
464 { 0x414c4300, "Realtek", cl(ac97_rl) },
465 { 0x414c4700, "Avance Logic", cl(ac97_av) },
466 { 0x434d4900, "C-Media Electronics", cl(ac97_cm) },
467 { 0x43525900, "Cirrus Logic", cl(ac97_cs) },
468 { 0x43585400, "Conexant", cl(ac97_cx) },
469 { 0x44543000, "Diamond Technology", cl(ac97_dt) },
470 { 0x454d4300, "eMicro", cl(ac97_em) },
471 { 0x45838300, "ESS Technology", cl(ac97_es) },
472 { 0x48525300, "Intersil", cl(ac97_is) },
473 { 0x49434500, "ICEnsemble", cl(ac97_ic) },
474 { 0x49544500, "ITE, Inc.", cl(ac97_it) },
475 { 0x4e534300, "National Semiconductor", cl(ac97_ns) },
476 { 0x50534300, "Philips Semiconductor", cl(ac97_ps) },
477 { 0x53494c00, "Silicon Laboratory", cl(ac97_sl) },
478 { 0x54524100, "TriTech Microelectronics", cl(ac97_tt) },
479 { 0x54584e00, "Texas Instruments", cl(ac97_ti) },
480 { 0x56494100, "VIA Technologies", cl(ac97_vi) },
481 { 0x57454300, "Winbond", cl(ac97_wb) },
482 { 0x574d4c00, "Wolfson", cl(ac97_wo) },
483 { 0x594d4800, "Yamaha", cl(ac97_ym) },
484 { 0x83847600, "SigmaTel", cl(ac97_st) },
485 };
486 #undef cl
487
488 const char * const ac97enhancement[] = {
489 "No 3D Stereo",
490 "Analog Devices Phat Stereo",
491 "Creative",
492 "National Semi 3D",
493 "Yamaha Ymersion",
494 "BBE 3D",
495 "Crystal Semi 3D",
496 "Qsound QXpander",
497 "Spatializer 3D",
498 "SRS 3D",
499 "Platform Tech 3D",
500 "AKM 3D",
501 "Aureal",
502 "AZTECH 3D",
503 "Binaura 3D",
504 "ESS Technology",
505 "Harman International VMAx",
506 "Nvidea 3D",
507 "Philips Incredible Sound",
508 "Texas Instruments 3D",
509 "VLSI Technology 3D",
510 "TriTech 3D",
511 "Realtek 3D",
512 "Samsung 3D",
513 "Wolfson Microelectronics 3D",
514 "Delta Integration 3D",
515 "SigmaTel 3D",
516 "KS Waves 3D",
517 "Rockwell 3D",
518 "Unknown 3D",
519 "Unknown 3D",
520 "Unknown 3D"
521 };
522
523 const char * const ac97feature[] = {
524 "mic channel",
525 "reserved",
526 "tone",
527 "simulated stereo",
528 "headphone",
529 "bass boost",
530 "18 bit DAC",
531 "20 bit DAC",
532 "18 bit ADC",
533 "20 bit ADC"
534 };
535
536
537 int ac97_str_equal(const char *, const char *);
538 void ac97_setup_source_info(struct ac97_softc *);
539 void ac97_setup_defaults(struct ac97_softc *);
540 int ac97_read(struct ac97_softc *, u_int8_t, u_int16_t *);
541 int ac97_write(struct ac97_softc *, u_int8_t, u_int16_t);
542
543
544 #ifdef AUDIO_DEBUG
545 #define DPRINTF(x) if (ac97debug) printf x
546 #define DPRINTFN(n,x) if (ac97debug>(n)) printf x
547 #ifdef AC97_DEBUG
548 int ac97debug = 1;
549 #else
550 int ac97debug = 0;
551 #endif
552 #else
553 #define DPRINTF(x)
554 #define DPRINTFN(n,x)
555 #endif
556
557 int
558 ac97_read(struct ac97_softc *as, u_int8_t reg, u_int16_t *val)
559 {
560 int error;
561
562 if (((as->host_flags & AC97_HOST_DONT_READ) &&
563 (reg != AC97_REG_VENDOR_ID1 && reg != AC97_REG_VENDOR_ID2 &&
564 reg != AC97_REG_RESET)) ||
565 (as->host_flags & AC97_HOST_DONT_READANY)) {
566 *val = as->shadow_reg[reg >> 1];
567 return (0);
568 }
569
570 if ((error = as->host_if->read(as->host_if->arg, reg, val)))
571 *val = as->shadow_reg[reg >> 1];
572 return (error);
573 }
574
575 int
576 ac97_write(struct ac97_softc *as, u_int8_t reg, u_int16_t val)
577 {
578 as->shadow_reg[reg >> 1] = val;
579 return (as->host_if->write(as->host_if->arg, reg, val));
580 }
581
582 void
583 ac97_setup_defaults(struct ac97_softc *as)
584 {
585 int idx;
586
587 bzero(as->shadow_reg, sizeof(as->shadow_reg));
588
589 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
590 const struct ac97_source_info *si = &source_info[idx];
591
592 ac97_write(as, si->reg, si->default_value);
593 }
594 }
595
596 void
597 ac97_restore_shadow(struct ac97_codec_if *self)
598 {
599 struct ac97_softc *as = (struct ac97_softc *)self;
600 int idx;
601
602 for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
603 const struct ac97_source_info *si = &source_info[idx];
604
605 ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
606 }
607 }
608
609 int
610 ac97_str_equal(const char *a, const char *b)
611 {
612 return ((a == b) || (a && b && (!strcmp(a, b))));
613 }
614
615 void
616 ac97_setup_source_info(struct ac97_softc *as)
617 {
618 struct ac97_source_info *si, *si2;
619 int idx, ouridx;
620
621 for (idx = 0, ouridx = 0; idx < SOURCE_INFO_SIZE; idx++) {
622 si = &as->source_info[ouridx];
623
624 bcopy(&source_info[idx], si, sizeof(*si));
625
626 switch (si->type) {
627 case AUDIO_MIXER_CLASS:
628 si->mixer_class = ouridx;
629 ouridx++;
630 break;
631 case AUDIO_MIXER_VALUE:
632
633 ouridx++;
634
635
636 if (si->mute) {
637 si = &as->source_info[ouridx];
638 bcopy(&source_info[idx], si, sizeof(*si));
639 si->qualifier = AudioNmute;
640 si->type = AUDIO_MIXER_ENUM;
641 si->info = &ac97_on_off;
642 si->info_size = sizeof(ac97_on_off);
643 si->bits = 1;
644 si->ofs = 15;
645 si->mute = 0;
646 si->polarity = 0;
647 ouridx++;
648 }
649 break;
650 case AUDIO_MIXER_ENUM:
651
652 ouridx++;
653 break;
654 default:
655 printf ("ac97: shouldn't get here\n");
656 break;
657 }
658 }
659
660 as->num_source_info = ouridx;
661
662 for (idx = 0; idx < as->num_source_info; idx++) {
663 int idx2, previdx;
664
665 si = &as->source_info[idx];
666
667
668 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
669 si2 = &as->source_info[idx2];
670
671 if (si2->type == AUDIO_MIXER_CLASS &&
672 ac97_str_equal(si->class, si2->class)) {
673 si->mixer_class = idx2;
674 }
675 }
676
677
678
679 if (si->prev != 0 || si->qualifier)
680 continue;
681
682 si->prev = AUDIO_MIXER_LAST;
683 previdx = idx;
684
685 for (idx2 = 0; idx2 < as->num_source_info; idx2++) {
686 if (idx2 == idx)
687 continue;
688
689 si2 = &as->source_info[idx2];
690
691 if (!si2->prev &&
692 ac97_str_equal(si->class, si2->class) &&
693 ac97_str_equal(si->device, si2->device)) {
694 as->source_info[previdx].next = idx2;
695 as->source_info[idx2].prev = previdx;
696
697 previdx = idx2;
698 }
699 }
700
701 as->source_info[previdx].next = AUDIO_MIXER_LAST;
702 }
703 }
704
705 int
706 ac97_attach(struct ac97_host_if *host_if)
707 {
708 struct ac97_softc *as;
709 u_int16_t id1, id2;
710 u_int32_t id;
711 mixer_ctrl_t ctl;
712 int error, i;
713 void (*initfunc)(struct ac97_softc *);
714
715 initfunc = NULL;
716
717 if (!(as = malloc(sizeof(struct ac97_softc), M_DEVBUF, M_NOWAIT)))
718 return (ENOMEM);
719
720 bzero(as, sizeof(*as));
721
722 as->codec_if.vtbl = &ac97civ;
723 as->host_if = host_if;
724
725 if ((error = host_if->attach(host_if->arg, &as->codec_if))) {
726 free(as, M_DEVBUF);
727 return (error);
728 }
729
730 host_if->reset(host_if->arg);
731 DELAY(1000);
732
733 host_if->write(host_if->arg, AC97_REG_POWER, 0);
734 host_if->write(host_if->arg, AC97_REG_RESET, 0);
735 DELAY(10000);
736
737 if (host_if->flags)
738 as->host_flags = host_if->flags(host_if->arg);
739
740 ac97_setup_defaults(as);
741 ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
742 ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
743 ac97_read(as, AC97_REG_RESET, &as->caps);
744
745 id = (id1 << 16) | id2;
746 if (id) {
747 register const struct ac97_vendorid *vendor;
748 register const struct ac97_codecid *codec;
749
750 printf("ac97: codec id 0x%08x", id);
751 for (vendor = &ac97_vendors[sizeof(ac97_vendors) /
752 sizeof(ac97_vendors[0]) - 1];
753 vendor >= ac97_vendors; vendor--) {
754 if (vendor->id == (id & AC97_VENDOR_ID_MASK)) {
755 printf(" (%s", vendor->name);
756 for (codec = &vendor->codecs[vendor->num-1];
757 codec >= vendor->codecs; codec--) {
758 if (codec->id == (id & codec->mask))
759 break;
760 }
761 if (codec >= vendor->codecs && codec->mask) {
762 printf(" %s", codec->name);
763 initfunc = codec->init;
764 } else
765 printf(" <%02x>", id & 0xff);
766 if (codec >= vendor->codecs && codec->rev)
767 printf(" rev %d", id & codec->rev);
768 printf(")");
769 break;
770 }
771 }
772 printf("\n");
773 } else
774 printf("ac97: codec id not read\n");
775
776 if (as->caps) {
777 printf("ac97: codec features ");
778 for (i = 0; i < 10; i++) {
779 if (as->caps & (1 << i))
780 printf("%s, ", ac97feature[i]);
781 }
782 printf("%s\n",
783 ac97enhancement[AC97_CAPS_ENHANCEMENT(as->caps)]);
784 }
785
786 ac97_read(as, AC97_REG_EXT_AUDIO_ID, &as->ext_id);
787 if (as->ext_id)
788 DPRINTF(("ac97: ext id %b\n", as->ext_id,
789 AC97_EXT_AUDIO_BITS));
790 if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_VRM)) {
791 ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &id1);
792 if (as->ext_id & AC97_EXT_AUDIO_VRA)
793 id1 |= AC97_EXT_AUDIO_VRA;
794 if (as->ext_id & AC97_EXT_AUDIO_VRM)
795 id1 |= AC97_EXT_AUDIO_VRM;
796 ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, id1);
797 }
798
799 ac97_setup_source_info(as);
800
801
802 if (initfunc != NULL)
803 initfunc(as);
804
805
806 bzero(&ctl, sizeof(ctl));
807
808 ctl.type = AUDIO_MIXER_ENUM;
809 ctl.un.ord = 0;
810 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCoutputs,
811 AudioNmaster, AudioNmute);
812 ac97_mixer_set_port(&as->codec_if, &ctl);
813
814 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCinputs,
815 AudioNdac, AudioNmute);
816 ac97_mixer_set_port(&as->codec_if, &ctl);
817
818 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
819 AudioNvolume, AudioNmute);
820 ac97_mixer_set_port(&as->codec_if, &ctl);
821
822 ctl.type = AUDIO_MIXER_ENUM;
823 ctl.un.ord = 0;
824 ctl.dev = ac97_get_portnum_by_name(&as->codec_if, AudioCrecord,
825 AudioNsource, NULL);
826 ac97_mixer_set_port(&as->codec_if, &ctl);
827
828 return (0);
829 }
830
831 int
832 ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip)
833 {
834 struct ac97_softc *as = (struct ac97_softc *)codec_if;
835
836 if (dip->index < as->num_source_info) {
837 struct ac97_source_info *si = &as->source_info[dip->index];
838 const char *name;
839
840 dip->type = si->type;
841 dip->mixer_class = si->mixer_class;
842 dip->prev = si->prev;
843 dip->next = si->next;
844
845 if (si->qualifier)
846 name = si->qualifier;
847 else if (si->device)
848 name = si->device;
849 else if (si->class)
850 name = si->class;
851
852 if (name)
853 strlcpy(dip->label.name, name, sizeof dip->label.name);
854
855 bcopy(si->info, &dip->un, si->info_size);
856
857
858 if (dip->type == AUDIO_MIXER_VALUE)
859 dip->un.v.delta = 1 << (8 - si->bits);
860
861 return (0);
862 }
863
864 return (ENXIO);
865 }
866
867 int
868 ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
869 {
870 struct ac97_softc *as = (struct ac97_softc *)codec_if;
871 struct ac97_source_info *si = &as->source_info[cp->dev];
872 u_int16_t mask;
873 u_int16_t val, newval;
874 int error;
875
876 if (cp->dev < 0 || cp->dev >= as->num_source_info ||
877 cp->type != si->type)
878 return (EINVAL);
879
880 ac97_read(as, si->reg, &val);
881
882 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
883
884 mask = (1 << si->bits) - 1;
885
886 switch (cp->type) {
887 case AUDIO_MIXER_ENUM:
888 if (cp->un.ord > mask || cp->un.ord < 0)
889 return (EINVAL);
890
891 newval = (cp->un.ord << si->ofs);
892 if (si->reg == AC97_REG_RECORD_SELECT) {
893 newval |= (newval << (8 + si->ofs));
894 mask |= (mask << 8);
895 }
896
897 if (si->mute) {
898 newval |= newval << 8;
899 mask |= mask << 8;
900 }
901
902 break;
903 case AUDIO_MIXER_VALUE:
904 {
905 const struct audio_mixer_value *value = si->info;
906 u_int16_t l, r;
907
908 if (cp->un.value.num_channels <= 0 ||
909 cp->un.value.num_channels > value->num_channels)
910 return (EINVAL);
911
912 if (cp->un.value.num_channels == 1) {
913 l = r = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
914 } else {
915 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
916 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
917 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
918 } else {
919 r = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
920 l = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
921 }
922 }
923
924 if (!si->polarity) {
925 l = 255 - l;
926 r = 255 - r;
927 }
928
929 l >>= 8 - si->bits;
930 r >>= 8 - si->bits;
931
932 newval = ((l & mask) << si->ofs);
933 if (value->num_channels == 2) {
934 newval |= ((r & mask) << (si->ofs + 8));
935 mask |= (mask << 8);
936 }
937
938 break;
939 }
940 default:
941 return (EINVAL);
942 }
943
944 mask = mask << si->ofs;
945 error = ac97_write(as, si->reg, (val & ~mask) | newval);
946 if (error)
947 return (error);
948
949 return (0);
950 }
951
952 int
953 ac97_get_portnum_by_name(struct ac97_codec_if *codec_if, char *class,
954 char *device, char *qualifier)
955 {
956 struct ac97_softc *as = (struct ac97_softc *)codec_if;
957 int idx;
958
959 for (idx = 0; idx < as->num_source_info; idx++) {
960 struct ac97_source_info *si = &as->source_info[idx];
961 if (ac97_str_equal(class, si->class) &&
962 ac97_str_equal(device, si->device) &&
963 ac97_str_equal(qualifier, si->qualifier))
964 return (idx);
965 }
966
967 return (-1);
968 }
969
970 int
971 ac97_mixer_get_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp)
972 {
973 struct ac97_softc *as = (struct ac97_softc *)codec_if;
974 struct ac97_source_info *si = &as->source_info[cp->dev];
975 u_int16_t mask;
976 u_int16_t val;
977
978 if (cp->dev < 0 || cp->dev >= as->num_source_info ||
979 cp->type != si->type)
980 return (EINVAL);
981
982 ac97_read(as, si->reg, &val);
983
984 DPRINTFN(5, ("read(%x) = %x\n", si->reg, val));
985
986 mask = (1 << si->bits) - 1;
987
988 switch (cp->type) {
989 case AUDIO_MIXER_ENUM:
990 cp->un.ord = (val >> si->ofs) & mask;
991 DPRINTFN(4, ("AUDIO_MIXER_ENUM: %x %d %x %d\n", val, si->ofs,
992 mask, cp->un.ord));
993 break;
994 case AUDIO_MIXER_VALUE:
995 {
996 const struct audio_mixer_value *value = si->info;
997 u_int16_t l, r;
998
999 if ((cp->un.value.num_channels <= 0) ||
1000 (cp->un.value.num_channels > value->num_channels))
1001 return (EINVAL);
1002
1003 if (value->num_channels == 1)
1004 l = r = (val >> si->ofs) & mask;
1005 else {
1006 if (!(as->host_flags & AC97_HOST_SWAPPED_CHANNELS)) {
1007 l = (val >> si->ofs) & mask;
1008 r = (val >> (si->ofs + 8)) & mask;
1009 } else {
1010 r = (val >> si->ofs) & mask;
1011 l = (val >> (si->ofs + 8)) & mask;
1012 }
1013 }
1014
1015 l <<= 8 - si->bits;
1016 r <<= 8 - si->bits;
1017 if (!si->polarity) {
1018 l = 255 - l;
1019 r = 255 - r;
1020 }
1021
1022
1023
1024
1025
1026
1027 if (cp->un.value.num_channels == 1) {
1028 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = l;
1029 } else if (cp->un.value.num_channels == 2) {
1030 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1031 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1032 }
1033
1034 break;
1035 }
1036 default:
1037 return (EINVAL);
1038 }
1039
1040 return (0);
1041 }
1042
1043 int
1044 ac97_set_rate(struct ac97_codec_if *codec_if, struct audio_params *p,
1045 int mode)
1046 {
1047 struct ac97_softc *as = (struct ac97_softc *)codec_if;
1048 u_int16_t reg, val, regval, id = 0;
1049
1050 DPRINTFN(5, ("set_rate(%lu) ", p->sample_rate));
1051
1052 if (!(as->ext_id & AC97_EXT_AUDIO_VRA)) {
1053 p->sample_rate = AC97_SINGLERATE;
1054 return (0);
1055 }
1056
1057 if (p->sample_rate > 0xffff) {
1058 if (mode != AUMODE_PLAY)
1059 return (EINVAL);
1060 if (!(as->ext_id & AC97_EXT_AUDIO_DRA))
1061 return (EINVAL);
1062 if (ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &id))
1063 return (EIO);
1064 id |= AC97_EXT_AUDIO_DRA;
1065 if (ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, id))
1066 return (EIO);
1067 p->sample_rate /= 2;
1068 }
1069
1070
1071 if (ac97_read(as, AC97_REG_POWER, &val) ||
1072 ac97_write(as, AC97_REG_POWER, val |
1073 (mode == AUMODE_PLAY? AC97_POWER_OUT : AC97_POWER_IN)))
1074 return (EIO);
1075
1076 reg = mode == AUMODE_PLAY ?
1077 AC97_REG_FRONT_DAC_RATE : AC97_REG_PCM_ADC_RATE;
1078
1079 if (ac97_write(as, reg, (u_int16_t) p->sample_rate) ||
1080 ac97_read(as, reg, ®val))
1081 return (EIO);
1082 p->sample_rate = regval;
1083 if (id & AC97_EXT_AUDIO_DRA)
1084 p->sample_rate *= 2;
1085
1086 DPRINTFN(5, (" %lu\n", regval));
1087
1088 if (ac97_write(as, AC97_REG_POWER, val))
1089 return (EIO);
1090
1091 return (0);
1092 }
1093
1094
1095
1096
1097
1098 #define AC97_AD1886_JACK_SENSE 0x72
1099
1100 void
1101 ac97_ad1886_init(struct ac97_softc *as)
1102 {
1103 ac97_write(as, AC97_AD1886_JACK_SENSE, 0x0010);
1104 }
1105
1106 void
1107 ac97_ad198x_init(struct ac97_softc *as)
1108 {
1109 int i;
1110 u_int16_t misc;
1111
1112 ac97_read(as, AC97_AD_REG_MISC, &misc);
1113 ac97_write(as, AC97_AD_REG_MISC,
1114 misc|AC97_AD_MISC_HPSEL|AC97_AD_MISC_LOSEL);
1115
1116 for (i = 0; i < as->num_source_info; i++) {
1117 if (as->source_info[i].reg == AC97_REG_SURROUND_VOLUME)
1118 as->source_info[i].reg = AC97_REG_MASTER_VOLUME;
1119 else if (as->source_info[i].reg == AC97_REG_MASTER_VOLUME) {
1120 as->source_info[i].reg = AC97_REG_SURROUND_VOLUME;
1121 if (as->source_info[i].type == AUDIO_MIXER_ENUM) {
1122 as->source_info[i].mute = 1;
1123 as->source_info[i].ofs = 7;
1124 }
1125 }
1126 }
1127 }
1128
1129 void
1130 ac97_alc655_init(struct ac97_softc *as)
1131 {
1132 u_int16_t misc;
1133
1134 ac97_read(as, AC97_AV_REG_MISC, &misc);
1135 if (as->host_flags & AC97_HOST_DONT_ENABLE_SPDIF) {
1136 misc &= ~AC97_AV_MISC_SPDIFEN;
1137 } else {
1138 misc |= AC97_AV_MISC_SPDIFEN;
1139 }
1140 misc &= ~AC97_AV_MISC_VREFDIS;
1141 ac97_write(as, AC97_AV_REG_MISC, misc);
1142
1143 ac97_write(as, AC97_AV_REG_MULTICH, AC97_AV_MULTICH_MAGIC);
1144 }
1145
1146 void
1147 ac97_cx20468_init(struct ac97_softc *as)
1148 {
1149 u_int16_t misc;
1150
1151 ac97_read(as, AC97_CX_REG_MISC, &misc);
1152 ac97_write(as, AC97_CX_REG_MISC, misc &
1153 ~(AC97_CX_SPDIFEN | AC97_CX_COPYRIGHT | AC97_CX_MASK));
1154 }