- Linus: more PageDirty / swapcache handling
[davej-history.git] / drivers / sound / ac97_codec.c
blob558161d28ea6da3e298a7f3a19319b13c855f0de
2 /*
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.
23 * History
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]))
57 static struct {
58 unsigned int id;
59 char *name;
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 {
127 int mixer;
128 unsigned int value;
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},
145 {-1,0}
148 /* table to scale scale from OSS mixer value to AC97 mixer register value */
149 static struct ac97_mixer_hw {
150 unsigned char offset;
151 int scale;
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 {
171 AC97_REC_MIC=0,
172 AC97_REC_CD,
173 AC97_REC_VIDEO,
174 AC97_REC_AUX,
175 AC97_REC_LINE,
176 AC97_REC_STEREO, /* combination of all enabled outputs.. */
177 AC97_REC_MONO, /*.. or the mono equivalent */
178 AC97_REC_PHONE
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)
206 u16 val;
207 int ret = 0;
208 int scale;
209 struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
211 val = codec->codec_read(codec , mh->offset);
213 if (val & AC97_MUTE) {
214 ret = 0;
215 } else if (AC97_STEREO_MASK & (1 << oss_channel)) {
216 /* nice stereo mixers .. */
217 int left,right;
219 left = (val >> 8) & 0x7f;
220 right = val & 0x7f;
222 if (oss_channel == SOUND_MIXER_IGAIN) {
223 right = (right * 100) / mh->scale;
224 left = (left * 100) / mh->scale;
225 } else {
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);
229 else
230 scale = mh->scale;
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);
253 #ifdef DEBUG
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);
258 #endif
260 return 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)
268 u16 val = 0;
269 int scale;
270 struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
272 #ifdef DEBUG
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);
277 #endif
279 if (AC97_STEREO_MASK & (1 << oss_channel)) {
280 /* stereo mixers */
281 if (left == 0 && right == 0) {
282 val = AC97_MUTE;
283 } else {
284 if (oss_channel == SOUND_MIXER_IGAIN) {
285 right = (right * mh->scale) / 100;
286 left = (left * mh->scale) / 100;
287 if (right >= mh->scale)
288 right = mh->scale-1;
289 if (left >= mh->scale)
290 left = mh->scale-1;
291 } else {
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);
296 else
297 scale = mh->scale;
299 right = ((100 - right) * scale) / 100;
300 left = ((100 - left) * scale) / 100;
301 if (right >= scale)
302 right = scale-1;
303 if (left >= scale)
304 left = scale-1;
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)
312 left = mh->scale-1;
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)
318 left = mh->scale-1;
319 val |= left & 0x000e;
320 } else if(left == 0) {
321 val = AC97_MUTE;
322 } else if (oss_channel == SOUND_MIXER_SPEAKER) {
323 left = ((100 - left) * mh->scale) / 100;
324 if (left >= mh->scale)
325 left = mh->scale-1;
326 val = left << 1;
327 } else if (oss_channel == SOUND_MIXER_PHONEIN) {
328 left = ((100 - left) * mh->scale) / 100;
329 if (left >= mh->scale)
330 left = mh->scale-1;
331 val = left;
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)
336 left = mh->scale-1;
337 val = left;
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)
342 left = mh->scale-1;
343 val |= left;
344 /* the low bit is optional in the tone sliders and masking
345 it lets us avoid the 0xf 'bypass'.. */
347 #ifdef DEBUG
348 printk(" 0x%04x", val);
349 #endif
351 codec->codec_write(codec, mh->offset, val);
353 #ifdef DEBUG
354 val = codec->codec_read(codec, mh->offset);
355 printk(" -> 0x%04x\n", val);
356 #endif
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)
381 unsigned int val;
383 if (rw) {
384 /* read it from the card */
385 val = codec->codec_read(codec, AC97_RECORD_SELECT);
386 #ifdef DEBUG
387 printk("ac97_codec: ac97 recmask to set to 0x%04x\n", val);
388 #endif
389 return (1 << ac97_rm2oss[val & 0x07]);
392 /* else, write the first set in the mask as the
393 output */
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]);
396 if (mask != val)
397 mask &= ~val;
399 val = ffs(mask);
400 val = ac97_oss_rm[val-1];
401 val |= val << 8; /* set both channels */
403 #ifdef DEBUG
404 printk("ac97_codec: setting ac97 recmask to 0x%04x\n", val);
405 #endif
407 codec->codec_write(codec, AC97_RECORD_SELECT, val);
409 return 0;
412 static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg)
414 int i, val = 0;
416 if (cmd == SOUND_MIXER_INFO) {
417 mixer_info 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)))
422 return -EFAULT;
423 return 0;
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)))
430 return -EFAULT;
431 return 0;
434 if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
435 return -EINVAL;
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) {
444 val = 0;
445 } else {
446 val = codec->recmask_io(codec, 1, 0);
448 break;
450 case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
451 val = codec->supported_mixers;
452 break;
454 case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
455 val = codec->record_sources;
456 break;
458 case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
459 val = codec->stereo_mixers;
460 break;
462 case SOUND_MIXER_CAPS:
463 val = SOUND_CAP_EXCL_INPUT;
464 break;
466 default: /* read a specific mixer */
467 i = _IOC_NR(cmd);
469 if (!supported_mixer(codec, i))
470 return -EINVAL;
472 /* do we ever want to touch the hardware? */
473 /* val = codec->read_mixer(codec, i); */
474 val = codec->mixer_state[i];
475 break;
477 return put_user(val, (int *)arg);
480 if (_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) {
481 codec->modcnt++;
482 if (get_user(val, (int *)arg))
483 return -EFAULT;
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;
488 if (!val) return 0;
489 if (!(val &= codec->record_sources)) return -EINVAL;
491 codec->recmask_io(codec, 0, val);
493 return 0;
494 default: /* write a specific mixer */
495 i = _IOC_NR(cmd);
497 if (!supported_mixer(codec, i))
498 return -EINVAL;
500 ac97_set_mixer(codec, i, val);
502 return 0;
505 return -EINVAL;
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;
514 int is_ac97_20 = 0;
516 if ((codec = data) == NULL)
517 return -ENODEV;
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-" : "");
538 val = cap & 0x00c0;
539 len += sprintf (page+len, "DAC resolutions :%s%s%s\n",
540 " -16-bit-",
541 val & 0x0040 ? " -18-bit-" : "",
542 val & 0x0080 ? " -20-bit-" : "");
543 val = cap & 0x0300;
544 len += sprintf (page+len, "ADC resolutions :%s%s%s\n",
545 " -16-bit-",
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"
553 "Sim. stereo : %s\n"
554 "3D enhancement : %s\n"
555 "Loudness : %s\n"
556 "Mono output : %s\n"
557 "MIC select : %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);
568 cap = extid;
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-" : "");
577 if (is_ac97_20) {
578 len += sprintf (page+len, "Front DAC rate : %d\n",
579 codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE));
582 return len;
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
603 * reset to complete.
605 * Returns 1 (true) on success, or 0 (false) on failure.
608 int ac97_probe_codec(struct ac97_codec *codec)
610 u16 id1, id2;
611 u16 audio, modem;
612 int i;
614 /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
615 * be read zero.
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);
625 else
626 udelay(10);
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");
631 return 0;
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);
638 codec->name = NULL;
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;
648 break;
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)
662 u16 cap;
663 int i;
665 cap = codec->codec_read(codec, AC97_RESET);
667 /* mixer masks */
668 codec->supported_mixers = AC97_SUPPORTED_MASK;
669 codec->stereo_mixers = AC97_STEREO_MASK;
670 codec->record_sources = AC97_RECORD_MASK;
671 if (!(cap & 0x04))
672 codec->supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE);
673 if (!(cap & 0x10))
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;
680 else
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];
697 if (md->mixer == -1)
698 break;
699 if (!supported_mixer(codec, md->mixer))
700 continue;
701 ac97_set_mixer(codec, md->mixer, md->value);
704 return 1;
707 static int sigmatel_init(struct ac97_codec * codec)
709 /* Only set up secondary codec */
710 if (codec->id == 0)
711 return 1;
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);
728 return 1;
732 * Bring up an AD1885
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);
739 return 0;
743 EXPORT_SYMBOL(ac97_read_proc);
744 EXPORT_SYMBOL(ac97_probe_codec);