3 * ac97_codec.c: Generic AC97 mixer/modem module
5 * Derived from ac97 mixer in maestro and trident driver.
7 * Copyright 2000 Silicon Integrated System Corporation
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * v0.4 Mar 15 2000 Ollie Lho
25 * dual codecs support verified with 4 channels output
26 * v0.3 Feb 22 2000 Ollie Lho
27 * bug fix for record mask setting
28 * v0.2 Feb 10 2000 Ollie Lho
29 * add ac97_read_proc for /proc/driver/{vendor}/ac97
30 * v0.1 Jan 14 2000 Ollie Lho <ollie@sis.com.tw>
31 * Isolated from trident.c to support multiple ac97 codec
33 #include <linux/module.h>
34 #include <linux/version.h>
35 #include <linux/kernel.h>
36 #include <linux/string.h>
37 #include <linux/errno.h>
38 #include <linux/bitops.h>
39 #include <linux/delay.h>
40 #include <linux/ac97_codec.h>
41 #include <asm/uaccess.h>
43 static int ac97_read_mixer(struct ac97_codec
*codec
, int oss_channel
);
44 static void ac97_write_mixer(struct ac97_codec
*codec
, int oss_channel
,
45 unsigned int left
, unsigned int right
);
46 static void ac97_set_mixer(struct ac97_codec
*codec
, unsigned int oss_mixer
, unsigned int val
);
47 static int ac97_recmask_io(struct ac97_codec
*codec
, int rw
, int mask
);
48 static int ac97_mixer_ioctl(struct ac97_codec
*codec
, unsigned int cmd
, unsigned long arg
);
50 static int ac97_init_mixer(struct ac97_codec
*codec
);
52 static int sigmatel_init(struct ac97_codec
*codec
);
53 static int enable_eapd(struct ac97_codec
*codec
);
55 #define arraysize(x) (sizeof(x)/sizeof((x)[0]))
60 int (*init
) (struct ac97_codec
*codec
);
61 } ac97_codec_ids
[] = {
62 {0x414B4D00, "Asahi Kasei AK4540 rev 0", NULL
},
63 {0x414B4D01, "Asahi Kasei AK4540 rev 1", NULL
},
64 {0x41445340, "Analog Devices AD1881" , NULL
},
65 {0x41445360, "Analog Devices AD1885" , enable_eapd
},
66 {0x43525900, "Cirrus Logic CS4297" , NULL
},
67 {0x43525903, "Cirrus Logic CS4297" , NULL
},
68 {0x43525913, "Cirrus Logic CS4297A" , NULL
},
69 {0x43525923, "Cirrus Logic CS4298" , NULL
},
70 {0x4352592B, "Cirrus Logic CS4294" , NULL
},
71 {0x43525931, "Cirrus Logic CS4299" , NULL
},
72 {0x43525934, "Cirrus Logic CS4299" , NULL
},
73 {0x4e534331, "National Semiconductor LM4549" , NULL
},
74 {0x53494c22, "Silicon Laboratory Si3036" , NULL
},
75 {0x53494c23, "Silicon Laboratory Si3038" , NULL
},
76 {0x83847600, "SigmaTel STAC????" , NULL
},
77 {0x83847604, "SigmaTel STAC9701/3/4/5", NULL
},
78 {0x83847605, "SigmaTel STAC9704" , NULL
},
79 {0x83847608, "SigmaTel STAC9708" , NULL
},
80 {0x83847609, "SigmaTel STAC9721/23" , sigmatel_init
},
81 {0x54524103, "TriTech TR?????" , NULL
},
82 {0x54524106, "TriTech TR28026" , NULL
},
83 {0x54524108, "TriTech TR28028" , NULL
},
84 {0x54524123, "TriTech TR?????" , NULL
},
85 {0x574D4C00, "Wolfson WM9704" , NULL
},
86 {0x00000000, NULL
, NULL
}
89 static const char *ac97_stereo_enhancements
[] =
91 /* 0 */ "No 3D Stereo Enhancement",
92 /* 1 */ "Analog Devices Phat Stereo",
93 /* 2 */ "Creative Stereo Enhancement",
94 /* 3 */ "National Semi 3D Stereo Enhancement",
95 /* 4 */ "YAMAHA Ymersion",
96 /* 5 */ "BBE 3D Stereo Enhancement",
97 /* 6 */ "Crystal Semi 3D Stereo Enhancement",
98 /* 7 */ "Qsound QXpander",
99 /* 8 */ "Spatializer 3D Stereo Enhancement",
100 /* 9 */ "SRS 3D Stereo Enhancement",
101 /* 10 */ "Platform Tech 3D Stereo Enhancement",
102 /* 11 */ "AKM 3D Audio",
103 /* 12 */ "Aureal Stereo Enhancement",
104 /* 13 */ "Aztech 3D Enhancement",
105 /* 14 */ "Binaura 3D Audio Enhancement",
106 /* 15 */ "ESS Technology Stereo Enhancement",
107 /* 16 */ "Harman International VMAx",
108 /* 17 */ "Nvidea 3D Stereo Enhancement",
109 /* 18 */ "Philips Incredible Sound",
110 /* 19 */ "Texas Instruments 3D Stereo Enhancement",
111 /* 20 */ "VLSI Technology 3D Stereo Enhancement",
112 /* 21 */ "TriTech 3D Stereo Enhancement",
113 /* 22 */ "Realtek 3D Stereo Enhancement",
114 /* 23 */ "Samsung 3D Stereo Enhancement",
115 /* 24 */ "Wolfson Microelectronics 3D Enhancement",
116 /* 25 */ "Delta Integration 3D Enhancement",
117 /* 26 */ "SigmaTel 3D Enhancement",
118 /* 27 */ "Reserved 27",
119 /* 28 */ "Rockwell 3D Stereo Enhancement",
120 /* 29 */ "Reserved 29",
121 /* 30 */ "Reserved 30",
122 /* 31 */ "Reserved 31"
125 /* this table has default mixer values for all OSS mixers. */
126 static struct mixer_defaults
{
129 } mixer_defaults
[SOUND_MIXER_NRDEVICES
] = {
130 /* all values 0 -> 100 in bytes */
131 {SOUND_MIXER_VOLUME
, 0x4343},
132 {SOUND_MIXER_BASS
, 0x4343},
133 {SOUND_MIXER_TREBLE
, 0x4343},
134 {SOUND_MIXER_PCM
, 0x4343},
135 {SOUND_MIXER_SPEAKER
, 0x4343},
136 {SOUND_MIXER_LINE
, 0x4343},
137 {SOUND_MIXER_MIC
, 0x4343},
138 {SOUND_MIXER_CD
, 0x4343},
139 {SOUND_MIXER_ALTPCM
, 0x4343},
140 {SOUND_MIXER_IGAIN
, 0x4343},
141 {SOUND_MIXER_LINE1
, 0x4343},
142 {SOUND_MIXER_PHONEIN
, 0x4343},
143 {SOUND_MIXER_PHONEOUT
, 0x4343},
144 {SOUND_MIXER_VIDEO
, 0x4343},
148 /* table to scale scale from OSS mixer value to AC97 mixer register value */
149 static struct ac97_mixer_hw
{
150 unsigned char offset
;
152 } ac97_hw
[SOUND_MIXER_NRDEVICES
]= {
153 [SOUND_MIXER_VOLUME
] = {AC97_MASTER_VOL_STEREO
,64},
154 [SOUND_MIXER_BASS
] = {AC97_MASTER_TONE
, 16},
155 [SOUND_MIXER_TREBLE
] = {AC97_MASTER_TONE
, 16},
156 [SOUND_MIXER_PCM
] = {AC97_PCMOUT_VOL
, 32},
157 [SOUND_MIXER_SPEAKER
] = {AC97_PCBEEP_VOL
, 16},
158 [SOUND_MIXER_LINE
] = {AC97_LINEIN_VOL
, 32},
159 [SOUND_MIXER_MIC
] = {AC97_MIC_VOL
, 32},
160 [SOUND_MIXER_CD
] = {AC97_CD_VOL
, 32},
161 [SOUND_MIXER_ALTPCM
] = {AC97_HEADPHONE_VOL
, 64},
162 [SOUND_MIXER_IGAIN
] = {AC97_RECORD_GAIN
, 16},
163 [SOUND_MIXER_LINE1
] = {AC97_AUX_VOL
, 32},
164 [SOUND_MIXER_PHONEIN
] = {AC97_PHONE_VOL
, 32},
165 [SOUND_MIXER_PHONEOUT
] = {AC97_MASTER_VOL_MONO
, 64},
166 [SOUND_MIXER_VIDEO
] = {AC97_VIDEO_VOL
, 32},
169 /* the following tables allow us to go from OSS <-> ac97 quickly. */
170 enum ac97_recsettings
{
176 AC97_REC_STEREO
, /* combination of all enabled outputs.. */
177 AC97_REC_MONO
, /*.. or the mono equivalent */
181 static unsigned int ac97_rm2oss
[] = {
182 [AC97_REC_MIC
] = SOUND_MIXER_MIC
,
183 [AC97_REC_CD
] = SOUND_MIXER_CD
,
184 [AC97_REC_VIDEO
] = SOUND_MIXER_VIDEO
,
185 [AC97_REC_AUX
] = SOUND_MIXER_LINE1
,
186 [AC97_REC_LINE
] = SOUND_MIXER_LINE
,
187 [AC97_REC_STEREO
]= SOUND_MIXER_IGAIN
,
188 [AC97_REC_PHONE
] = SOUND_MIXER_PHONEIN
191 /* indexed by bit position */
192 static unsigned int ac97_oss_rm
[] = {
193 [SOUND_MIXER_MIC
] = AC97_REC_MIC
,
194 [SOUND_MIXER_CD
] = AC97_REC_CD
,
195 [SOUND_MIXER_VIDEO
] = AC97_REC_VIDEO
,
196 [SOUND_MIXER_LINE1
] = AC97_REC_AUX
,
197 [SOUND_MIXER_LINE
] = AC97_REC_LINE
,
198 [SOUND_MIXER_IGAIN
] = AC97_REC_STEREO
,
199 [SOUND_MIXER_PHONEIN
] = AC97_REC_PHONE
202 /* reads the given OSS mixer from the ac97 the caller must have insured that the ac97 knows
203 about that given mixer, and should be holding a spinlock for the card */
204 static int ac97_read_mixer(struct ac97_codec
*codec
, int oss_channel
)
209 struct ac97_mixer_hw
*mh
= &ac97_hw
[oss_channel
];
211 val
= codec
->codec_read(codec
, mh
->offset
);
213 if (val
& AC97_MUTE
) {
215 } else if (AC97_STEREO_MASK
& (1 << oss_channel
)) {
216 /* nice stereo mixers .. */
219 left
= (val
>> 8) & 0x7f;
222 if (oss_channel
== SOUND_MIXER_IGAIN
) {
223 right
= (right
* 100) / mh
->scale
;
224 left
= (left
* 100) / mh
->scale
;
226 /* these may have 5 or 6 bit resolution */
227 if(oss_channel
== SOUND_MIXER_VOLUME
|| oss_channel
== SOUND_MIXER_ALTPCM
)
228 scale
= (1 << codec
->bit_resolution
);
232 right
= 100 - ((right
* 100) / scale
);
233 left
= 100 - ((left
* 100) / scale
);
235 ret
= left
| (right
<< 8);
236 } else if (oss_channel
== SOUND_MIXER_SPEAKER
) {
237 ret
= 100 - ((((val
& 0x1e)>>1) * 100) / mh
->scale
);
238 } else if (oss_channel
== SOUND_MIXER_PHONEIN
) {
239 ret
= 100 - (((val
& 0x1f) * 100) / mh
->scale
);
240 } else if (oss_channel
== SOUND_MIXER_PHONEOUT
) {
241 scale
= (1 << codec
->bit_resolution
);
242 ret
= 100 - (((val
& 0x1f) * 100) / scale
);
243 } else if (oss_channel
== SOUND_MIXER_MIC
) {
244 ret
= 100 - (((val
& 0x1f) * 100) / mh
->scale
);
245 /* the low bit is optional in the tone sliders and masking
246 it lets us avoid the 0xf 'bypass'.. */
247 } else if (oss_channel
== SOUND_MIXER_BASS
) {
248 ret
= 100 - ((((val
>> 8) & 0xe) * 100) / mh
->scale
);
249 } else if (oss_channel
== SOUND_MIXER_TREBLE
) {
250 ret
= 100 - (((val
& 0xe) * 100) / mh
->scale
);
254 printk("ac97_codec: read OSS mixer %2d (%s ac97 register 0x%02x), "
255 "0x%04x -> 0x%04x\n",
256 oss_channel
, codec
->id
? "Secondary" : "Primary",
257 mh
->offset
, val
, ret
);
263 /* write the OSS encoded volume to the given OSS encoded mixer, again caller's job to
264 make sure all is well in arg land, call with spinlock held */
265 static void ac97_write_mixer(struct ac97_codec
*codec
, int oss_channel
,
266 unsigned int left
, unsigned int right
)
270 struct ac97_mixer_hw
*mh
= &ac97_hw
[oss_channel
];
273 printk("ac97_codec: wrote OSS mixer %2d (%s ac97 register 0x%02x), "
274 "left vol:%2d, right vol:%2d:",
275 oss_channel
, codec
->id
? "Secondary" : "Primary",
276 mh
->offset
, left
, right
);
279 if (AC97_STEREO_MASK
& (1 << oss_channel
)) {
281 if (left
== 0 && right
== 0) {
284 if (oss_channel
== SOUND_MIXER_IGAIN
) {
285 right
= (right
* mh
->scale
) / 100;
286 left
= (left
* mh
->scale
) / 100;
287 if (right
>= mh
->scale
)
289 if (left
>= mh
->scale
)
292 /* these may have 5 or 6 bit resolution */
293 if (oss_channel
== SOUND_MIXER_VOLUME
||
294 oss_channel
== SOUND_MIXER_ALTPCM
)
295 scale
= (1 << codec
->bit_resolution
);
299 right
= ((100 - right
) * scale
) / 100;
300 left
= ((100 - left
) * scale
) / 100;
306 val
= (left
<< 8) | right
;
308 } else if (oss_channel
== SOUND_MIXER_BASS
) {
309 val
= codec
->codec_read(codec
, mh
->offset
) & ~0x0f00;
310 left
= ((100 - left
) * mh
->scale
) / 100;
311 if (left
>= mh
->scale
)
313 val
|= (left
<< 8) & 0x0e00;
314 } else if (oss_channel
== SOUND_MIXER_TREBLE
) {
315 val
= codec
->codec_read(codec
, mh
->offset
) & ~0x000f;
316 left
= ((100 - left
) * mh
->scale
) / 100;
317 if (left
>= mh
->scale
)
319 val
|= left
& 0x000e;
320 } else if(left
== 0) {
322 } else if (oss_channel
== SOUND_MIXER_SPEAKER
) {
323 left
= ((100 - left
) * mh
->scale
) / 100;
324 if (left
>= mh
->scale
)
327 } else if (oss_channel
== SOUND_MIXER_PHONEIN
) {
328 left
= ((100 - left
) * mh
->scale
) / 100;
329 if (left
>= mh
->scale
)
332 } else if (oss_channel
== SOUND_MIXER_PHONEOUT
) {
333 scale
= (1 << codec
->bit_resolution
);
334 left
= ((100 - left
) * scale
) / 100;
335 if (left
>= mh
->scale
)
338 } else if (oss_channel
== SOUND_MIXER_MIC
) {
339 val
= codec
->codec_read(codec
, mh
->offset
) & ~0x801f;
340 left
= ((100 - left
) * mh
->scale
) / 100;
341 if (left
>= mh
->scale
)
344 /* the low bit is optional in the tone sliders and masking
345 it lets us avoid the 0xf 'bypass'.. */
348 printk(" 0x%04x", val
);
351 codec
->codec_write(codec
, mh
->offset
, val
);
354 val
= codec
->codec_read(codec
, mh
->offset
);
355 printk(" -> 0x%04x\n", val
);
359 /* a thin wrapper for write_mixer */
360 static void ac97_set_mixer(struct ac97_codec
*codec
, unsigned int oss_mixer
, unsigned int val
)
362 unsigned int left
,right
;
364 /* cleanse input a little */
365 right
= ((val
>> 8) & 0xff) ;
366 left
= (val
& 0xff) ;
368 if (right
> 100) right
= 100;
369 if (left
> 100) left
= 100;
371 codec
->mixer_state
[oss_mixer
] = (right
<< 8) | left
;
372 codec
->write_mixer(codec
, oss_mixer
, left
, right
);
375 /* read or write the recmask, the ac97 can really have left and right recording
376 inputs independantly set, but OSS doesn't seem to want us to express that to
377 the user. the caller guarantees that we have a supported bit set, and they
378 must be holding the card's spinlock */
379 static int ac97_recmask_io(struct ac97_codec
*codec
, int rw
, int mask
)
384 /* read it from the card */
385 val
= codec
->codec_read(codec
, AC97_RECORD_SELECT
);
387 printk("ac97_codec: ac97 recmask to set to 0x%04x\n", val
);
389 return (1 << ac97_rm2oss
[val
& 0x07]);
392 /* else, write the first set in the mask as the
394 /* clear out current set value first (AC97 supports only 1 input!) */
395 val
= (1 << ac97_rm2oss
[codec
->codec_read(codec
, AC97_RECORD_SELECT
) & 0x07]);
400 val
= ac97_oss_rm
[val
-1];
401 val
|= val
<< 8; /* set both channels */
404 printk("ac97_codec: setting ac97 recmask to 0x%04x\n", val
);
407 codec
->codec_write(codec
, AC97_RECORD_SELECT
, val
);
412 static int ac97_mixer_ioctl(struct ac97_codec
*codec
, unsigned int cmd
, unsigned long arg
)
416 if (cmd
== SOUND_MIXER_INFO
) {
418 strncpy(info
.id
, codec
->name
, sizeof(info
.id
));
419 strncpy(info
.name
, codec
->name
, sizeof(info
.name
));
420 info
.modify_counter
= codec
->modcnt
;
421 if (copy_to_user((void *)arg
, &info
, sizeof(info
)))
425 if (cmd
== SOUND_OLD_MIXER_INFO
) {
426 _old_mixer_info info
;
427 strncpy(info
.id
, codec
->name
, sizeof(info
.id
));
428 strncpy(info
.name
, codec
->name
, sizeof(info
.name
));
429 if (copy_to_user((void *)arg
, &info
, sizeof(info
)))
434 if (_IOC_TYPE(cmd
) != 'M' || _IOC_SIZE(cmd
) != sizeof(int))
437 if (cmd
== OSS_GETVERSION
)
438 return put_user(SOUND_VERSION
, (int *)arg
);
440 if (_IOC_DIR(cmd
) == _IOC_READ
) {
441 switch (_IOC_NR(cmd
)) {
442 case SOUND_MIXER_RECSRC
: /* give them the current record source */
443 if (!codec
->recmask_io
) {
446 val
= codec
->recmask_io(codec
, 1, 0);
450 case SOUND_MIXER_DEVMASK
: /* give them the supported mixers */
451 val
= codec
->supported_mixers
;
454 case SOUND_MIXER_RECMASK
: /* Arg contains a bit for each supported recording source */
455 val
= codec
->record_sources
;
458 case SOUND_MIXER_STEREODEVS
: /* Mixer channels supporting stereo */
459 val
= codec
->stereo_mixers
;
462 case SOUND_MIXER_CAPS
:
463 val
= SOUND_CAP_EXCL_INPUT
;
466 default: /* read a specific mixer */
469 if (!supported_mixer(codec
, i
))
472 /* do we ever want to touch the hardware? */
473 /* val = codec->read_mixer(codec, i); */
474 val
= codec
->mixer_state
[i
];
477 return put_user(val
, (int *)arg
);
480 if (_IOC_DIR(cmd
) == (_IOC_WRITE
|_IOC_READ
)) {
482 if (get_user(val
, (int *)arg
))
485 switch (_IOC_NR(cmd
)) {
486 case SOUND_MIXER_RECSRC
: /* Arg contains a bit for each recording source */
487 if (!codec
->recmask_io
) return -EINVAL
;
489 if (!(val
&= codec
->record_sources
)) return -EINVAL
;
491 codec
->recmask_io(codec
, 0, val
);
494 default: /* write a specific mixer */
497 if (!supported_mixer(codec
, i
))
500 ac97_set_mixer(codec
, i
, val
);
508 /* entry point for /proc/driver/controller_vendor/ac97/%d */
509 int ac97_read_proc (char *page
, char **start
, off_t off
,
510 int count
, int *eof
, void *data
)
512 int len
= 0, cap
, extid
, val
, id1
, id2
;
513 struct ac97_codec
*codec
;
516 if ((codec
= data
) == NULL
)
519 id1
= codec
->codec_read(codec
, AC97_VENDOR_ID1
);
520 id2
= codec
->codec_read(codec
, AC97_VENDOR_ID2
);
521 len
+= sprintf (page
+len
, "Vendor name : %s\n", codec
->name
);
522 len
+= sprintf (page
+len
, "Vendor id : %04X %04X\n", id1
, id2
);
524 extid
= codec
->codec_read(codec
, AC97_EXTENDED_ID
);
525 extid
&= ~((1<<2)|(1<<4)|(1<<5)|(1<<10)|(1<<11)|(1<<12)|(1<<13));
526 len
+= sprintf (page
+len
, "AC97 Version : %s\n",
527 extid
? "2.0 or later" : "1.0");
528 if (extid
) is_ac97_20
= 1;
530 cap
= codec
->codec_read(codec
, AC97_RESET
);
531 len
+= sprintf (page
+len
, "Capabilities :%s%s%s%s%s%s\n",
532 cap
& 0x0001 ? " -dedicated MIC PCM IN channel-" : "",
533 cap
& 0x0002 ? " -reserved1-" : "",
534 cap
& 0x0004 ? " -bass & treble-" : "",
535 cap
& 0x0008 ? " -simulated stereo-" : "",
536 cap
& 0x0010 ? " -headphone out-" : "",
537 cap
& 0x0020 ? " -loudness-" : "");
539 len
+= sprintf (page
+len
, "DAC resolutions :%s%s%s\n",
541 val
& 0x0040 ? " -18-bit-" : "",
542 val
& 0x0080 ? " -20-bit-" : "");
544 len
+= sprintf (page
+len
, "ADC resolutions :%s%s%s\n",
546 val
& 0x0100 ? " -18-bit-" : "",
547 val
& 0x0200 ? " -20-bit-" : "");
548 len
+= sprintf (page
+len
, "3D enhancement : %s\n",
549 ac97_stereo_enhancements
[(cap
>> 10) & 0x1f]);
551 val
= codec
->codec_read(codec
, AC97_GENERAL_PURPOSE
);
552 len
+= sprintf (page
+len
, "POP path : %s 3D\n"
554 "3D enhancement : %s\n"
558 "ADC/DAC loopback : %s\n",
559 val
& 0x8000 ? "post" : "pre",
560 val
& 0x4000 ? "on" : "off",
561 val
& 0x2000 ? "on" : "off",
562 val
& 0x1000 ? "on" : "off",
563 val
& 0x0200 ? "MIC" : "MIX",
564 val
& 0x0100 ? "MIC2" : "MIC1",
565 val
& 0x0080 ? "on" : "off");
567 extid
= codec
->codec_read(codec
, AC97_EXTENDED_ID
);
569 len
+= sprintf (page
+len
, "Ext Capabilities :%s%s%s%s%s%s%s\n",
570 cap
& 0x0001 ? " -var rate PCM audio-" : "",
571 cap
& 0x0002 ? " -2x PCM audio out-" : "",
572 cap
& 0x0008 ? " -var rate MIC in-" : "",
573 cap
& 0x0040 ? " -PCM center DAC-" : "",
574 cap
& 0x0080 ? " -PCM surround DAC-" : "",
575 cap
& 0x0100 ? " -PCM LFE DAC-" : "",
576 cap
& 0x0200 ? " -slot/DAC mappings-" : "");
578 len
+= sprintf (page
+len
, "Front DAC rate : %d\n",
579 codec
->codec_read(codec
, AC97_PCM_FRONT_DAC_RATE
));
586 * ac97_probe_codec - Initialize and setup AC97-compatible codec
587 * @codec: (in/out) Kernel info for a single AC97 codec
589 * Reset the AC97 codec, then initialize the mixer and
590 * the rest of the @codec structure.
592 * The codec_read and codec_write fields of @codec are
593 * required to be setup and working when this function
594 * is called. All other fields are set by this function.
596 * codec_wait field of @codec can optionally be provided
597 * when calling this function. If codec_wait is not %NULL,
598 * this function will call codec_wait any time it is
599 * necessary to wait for the audio chip to reach the
600 * codec-ready state. If codec_wait is %NULL, then
601 * the default behavior is to call schedule_timeout.
602 * Currently codec_wait is used to wait for AC97 codec
605 * Returns 1 (true) on success, or 0 (false) on failure.
608 int ac97_probe_codec(struct ac97_codec
*codec
)
614 /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
617 * FIXME: is the following comment outdated? -jgarzik
618 * Probing of AC97 in this way is not reliable, it is not even SAFE !!
620 codec
->codec_write(codec
, AC97_RESET
, 0L);
622 /* also according to spec, we wait for codec-ready state */
623 if (codec
->codec_wait
)
624 codec
->codec_wait(codec
);
628 if ((audio
= codec
->codec_read(codec
, AC97_RESET
)) & 0x8000) {
629 printk(KERN_ERR
"ac97_codec: %s ac97 codec not present\n",
630 codec
->id
? "Secondary" : "Primary");
634 /* probe for Modem Codec */
635 codec
->codec_write(codec
, AC97_EXTENDED_MODEM_ID
, 0L);
636 modem
= codec
->codec_read(codec
, AC97_EXTENDED_MODEM_ID
);
639 codec
->codec_init
= NULL
;
641 id1
= codec
->codec_read(codec
, AC97_VENDOR_ID1
);
642 id2
= codec
->codec_read(codec
, AC97_VENDOR_ID2
);
643 for (i
= 0; i
< arraysize(ac97_codec_ids
); i
++) {
644 if (ac97_codec_ids
[i
].id
== ((id1
<< 16) | id2
)) {
645 codec
->type
= ac97_codec_ids
[i
].id
;
646 codec
->name
= ac97_codec_ids
[i
].name
;
647 codec
->codec_init
= ac97_codec_ids
[i
].init
;
651 if (codec
->name
== NULL
)
652 codec
->name
= "Unknown";
653 printk(KERN_INFO
"ac97_codec: AC97 %s codec, id: 0x%04x:"
654 "0x%04x (%s)\n", audio
? "Audio" : (modem
? "Modem" : ""),
655 id1
, id2
, codec
->name
);
657 return ac97_init_mixer(codec
);
660 static int ac97_init_mixer(struct ac97_codec
*codec
)
665 cap
= codec
->codec_read(codec
, AC97_RESET
);
668 codec
->supported_mixers
= AC97_SUPPORTED_MASK
;
669 codec
->stereo_mixers
= AC97_STEREO_MASK
;
670 codec
->record_sources
= AC97_RECORD_MASK
;
672 codec
->supported_mixers
&= ~(SOUND_MASK_BASS
|SOUND_MASK_TREBLE
);
674 codec
->supported_mixers
&= ~SOUND_MASK_ALTPCM
;
676 /* detect bit resolution */
677 codec
->codec_write(codec
, AC97_MASTER_VOL_STEREO
, 0x2020);
678 if(codec
->codec_read(codec
, AC97_MASTER_VOL_STEREO
) == 0x1f1f)
679 codec
->bit_resolution
= 5;
681 codec
->bit_resolution
= 6;
683 /* generic OSS to AC97 wrapper */
684 codec
->read_mixer
= ac97_read_mixer
;
685 codec
->write_mixer
= ac97_write_mixer
;
686 codec
->recmask_io
= ac97_recmask_io
;
687 codec
->mixer_ioctl
= ac97_mixer_ioctl
;
689 /* codec specific initialization for 4-6 channel output or secondary codec stuff */
690 if (codec
->codec_init
!= NULL
) {
691 codec
->codec_init(codec
);
694 /* initilize mixer channel volumes */
695 for (i
= 0; i
< SOUND_MIXER_NRDEVICES
; i
++) {
696 struct mixer_defaults
*md
= &mixer_defaults
[i
];
699 if (!supported_mixer(codec
, md
->mixer
))
701 ac97_set_mixer(codec
, md
->mixer
, md
->value
);
707 static int sigmatel_init(struct ac97_codec
* codec
)
709 /* Only set up secondary codec */
713 codec
->codec_write(codec
, AC97_SURROUND_MASTER
, 0L);
715 /* initialize SigmaTel STAC9721/23 as secondary codec, decoding AC link
716 sloc 3,4 = 0x01, slot 7,8 = 0x00, */
717 codec
->codec_write(codec
, 0x74, 0x00);
719 /* we don't have the crystal when we are on an AMR card, so use
720 BIT_CLK as our clock source. Write the magic word ABBA and read
721 back to enable register 0x78 */
722 codec
->codec_write(codec
, 0x76, 0xabba);
723 codec
->codec_read(codec
, 0x76);
725 /* sync all the clocks*/
726 codec
->codec_write(codec
, 0x78, 0x3802);
735 static int enable_eapd(struct ac97_codec
* codec
)
737 codec
->codec_write(codec
, AC97_POWER_CONTROL
,
738 codec
->codec_read(codec
, AC97_POWER_CONTROL
)|0x8000);
743 EXPORT_SYMBOL(ac97_read_proc
);
744 EXPORT_SYMBOL(ac97_probe_codec
);