Merge with 2.3.48.
[linux-2.6/linux-mips.git] / drivers / sound / ac97_codec.c
blob175cd38e05239f8297f324c62ce72067e3f735b8
1 /*
2 * ac97_codec.c: Generic AC97 mixer module
4 * Derived from ac97 mixer in maestro and trident driver.
6 * Copyright 2000 Silicon Integrated System Corporation
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * History
23 * v0.2 Feb 10 2000 Ollie Lho
24 * add ac97_read_proc for /proc/driver/vnedor/ac97
25 * v0.1 Jan 14 2000 Ollie Lho <ollie@sis.com.tw>
26 * Isolated from trident.c to support multiple ac97 codec
28 #include <linux/module.h>
29 #include <linux/version.h>
30 #include <linux/kernel.h>
31 #include <linux/ac97_codec.h>
33 static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel);
34 static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
35 unsigned int left, unsigned int right);
36 static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val );
37 static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask);
38 static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
40 #define arraysize(x) (sizeof(x)/sizeof((x)[0]))
42 static struct {
43 unsigned int id;
44 char *name;
45 int (*init) (struct ac97_codec *codec);
46 } ac97_codec_ids[] = {
47 {0x414B4D00, "Asahi Kasei AK4540" , NULL},
48 {0x41445340, "Analog Devices AD1881" , NULL},
49 {0x43525900, "Cirrus Logic CS4297" , NULL},
50 {0x43525913, "Cirrus Logic CS4297A" , NULL},
51 {0x43525931, "Cirrus Logic CS4299" , NULL},
52 {0x4e534331, "National Semiconductor LM4549", NULL},
53 {0x83847600, "SigmaTel STAC????" , NULL},
54 {0x83847604, "SigmaTel STAC9701/3/4/5", NULL},
55 {0x83847605, "SigmaTel STAC9704" , NULL},
56 {0x83847608, "SigmaTel STAC9708" , NULL},
57 {0x83847609, "SigmaTel STAC9721/23" , NULL},
58 {0x54524108, "TriTech TR28028" , NULL},
59 {0x574D4C00, "Wolfson WM9704" , NULL},
60 {0x00000000, NULL, NULL}
63 static const char *ac97_stereo_enhancements[] =
65 /* 0 */ "No 3D Stereo Enhancement",
66 /* 1 */ "Analog Devices Phat Stereo",
67 /* 2 */ "Creative Stereo Enhancement",
68 /* 3 */ "National Semi 3D Stereo Enhancement",
69 /* 4 */ "YAMAHA Ymersion",
70 /* 5 */ "BBE 3D Stereo Enhancement",
71 /* 6 */ "Crystal Semi 3D Stereo Enhancement",
72 /* 7 */ "Qsound QXpander",
73 /* 8 */ "Spatializer 3D Stereo Enhancement",
74 /* 9 */ "SRS 3D Stereo Enhancement",
75 /* 10 */ "Platform Tech 3D Stereo Enhancement",
76 /* 11 */ "AKM 3D Audio",
77 /* 12 */ "Aureal Stereo Enhancement",
78 /* 13 */ "Aztech 3D Enhancement",
79 /* 14 */ "Binaura 3D Audio Enhancement",
80 /* 15 */ "ESS Technology Stereo Enhancement",
81 /* 16 */ "Harman International VMAx",
82 /* 17 */ "Nvidea 3D Stereo Enhancement",
83 /* 18 */ "Philips Incredible Sound",
84 /* 19 */ "Texas Instruments 3D Stereo Enhancement",
85 /* 20 */ "VLSI Technology 3D Stereo Enhancement",
86 /* 21 */ "TriTech 3D Stereo Enhancement",
87 /* 22 */ "Realtek 3D Stereo Enhancement",
88 /* 23 */ "Samsung 3D Stereo Enhancement",
89 /* 24 */ "Wolfson Microelectronics 3D Enhancement",
90 /* 25 */ "Delta Integration 3D Enhancement",
91 /* 26 */ "SigmaTel 3D Enhancement",
92 /* 27 */ "Reserved 27",
93 /* 28 */ "Rockwell 3D Stereo Enhancement",
94 /* 29 */ "Reserved 29",
95 /* 30 */ "Reserved 30",
96 /* 31 */ "Reserved 31"
99 /* this table has default mixer values for all OSS mixers. */
100 static struct mixer_defaults {
101 int mixer;
102 unsigned int value;
103 } mixer_defaults[SOUND_MIXER_NRDEVICES] = {
104 /* all values 0 -> 100 in bytes */
105 {SOUND_MIXER_VOLUME, 0x3232},
106 {SOUND_MIXER_BASS, 0x3232},
107 {SOUND_MIXER_TREBLE, 0x3232},
108 {SOUND_MIXER_PCM, 0x3232},
109 {SOUND_MIXER_SPEAKER, 0x3232},
110 {SOUND_MIXER_LINE, 0x3232},
111 {SOUND_MIXER_MIC, 0x3232},
112 {SOUND_MIXER_CD, 0x3232},
113 {SOUND_MIXER_ALTPCM, 0x3232},
114 {SOUND_MIXER_IGAIN, 0x3232},
115 {SOUND_MIXER_LINE1, 0x3232},
116 {SOUND_MIXER_PHONEIN, 0x3232},
117 {SOUND_MIXER_PHONEOUT, 0x3232},
118 {SOUND_MIXER_VIDEO, 0x3232},
119 {-1,0}
122 /* table to scale scale from OSS mixer value to AC97 mixer register value */
123 static struct ac97_mixer_hw {
124 unsigned char offset;
125 int scale;
126 } ac97_hw[SOUND_MIXER_NRDEVICES]= {
127 [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,63},
128 [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 15},
129 [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 15},
130 [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 31},
131 [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 15},
132 [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 31},
133 [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 31},
134 [SOUND_MIXER_CD] = {AC97_CD_VOL, 31},
135 [SOUND_MIXER_ALTPCM] = {AC97_HEADPHONE_VOL, 63},
136 [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 31},
137 [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 31},
138 [SOUND_MIXER_PHONEIN] = {AC97_PHONE_VOL, 15},
139 [SOUND_MIXER_PHONEOUT] = {AC97_MASTER_VOL_MONO, 63},
140 [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 31},
143 /* the following tables allow us to go from OSS <-> ac97 quickly. */
144 enum ac97_recsettings {
145 AC97_REC_MIC=0,
146 AC97_REC_CD,
147 AC97_REC_VIDEO,
148 AC97_REC_AUX,
149 AC97_REC_LINE,
150 AC97_REC_STEREO, /* combination of all enabled outputs.. */
151 AC97_REC_MONO, /*.. or the mono equivalent */
152 AC97_REC_PHONE
155 static unsigned int ac97_rm2oss[] = {
156 [AC97_REC_MIC] = SOUND_MIXER_MIC,
157 [AC97_REC_CD] = SOUND_MIXER_CD,
158 [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
159 [AC97_REC_AUX] = SOUND_MIXER_LINE1,
160 [AC97_REC_LINE] = SOUND_MIXER_LINE,
161 [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
164 /* indexed by bit position */
165 static unsigned int ac97_oss_rm[] = {
166 [SOUND_MIXER_MIC] = AC97_REC_MIC,
167 [SOUND_MIXER_CD] = AC97_REC_CD,
168 [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
169 [SOUND_MIXER_LINE1] = AC97_REC_AUX,
170 [SOUND_MIXER_LINE] = AC97_REC_LINE,
171 [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
174 /* reads the given OSS mixer from the ac97 the caller must have insured that the ac97 knows
175 about that given mixer, and should be holding a spinlock for the card */
176 static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel)
178 u16 val;
179 int ret = 0;
180 struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
182 val = codec->codec_read(codec , mh->offset);
184 if (AC97_STEREO_MASK & (1 << oss_channel)) {
185 /* nice stereo mixers .. */
186 int left,right;
188 left = (val >> 8) & 0x7f;
189 right = val & 0x7f;
191 if (oss_channel == SOUND_MIXER_IGAIN) {
192 right = (right * 100) / mh->scale;
193 left = (left * 100) / mh->scale;
194 } else {
195 right = 100 - ((right * 100) / mh->scale);
196 left = 100 - ((left * 100) / mh->scale);
198 ret = left | (right << 8);
199 } else if (oss_channel == SOUND_MIXER_SPEAKER) {
200 ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);
201 } else if (oss_channel == SOUND_MIXER_PHONEIN) {
202 ret = 100 - (((val & 0x1f) * 100) / mh->scale);
203 } else if (oss_channel == SOUND_MIXER_PHONEOUT) {
204 ret = 100 - (((val & 0x1f) * 100) / mh->scale);
205 } else if (oss_channel == SOUND_MIXER_MIC) {
206 ret = 100 - (((val & 0x1f) * 100) / mh->scale);
207 /* the low bit is optional in the tone sliders and masking
208 it lets us avoid the 0xf 'bypass'.. */
209 } else if (oss_channel == SOUND_MIXER_BASS) {
210 ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale);
211 } else if (oss_channel == SOUND_MIXER_TREBLE) {
212 ret = 100 - (((val & 0xe) * 100) / mh->scale);
215 #ifdef DEBUG
216 printk("ac97_codec: read OSS mixer %2d (ac97 register 0x%02x), "
217 "0x%04x -> 0x%04x\n", oss_channel, mh->offset, val, ret);
218 #endif
220 return ret;
223 /* write the OSS encoded volume to the given OSS encoded mixer, again caller's job to
224 make sure all is well in arg land, call with spinlock held */
225 static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
226 unsigned int left, unsigned int right)
228 u16 val = 0;
229 struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
231 #ifdef DEBUG
232 printk("ac97_codec: wrote OSS mixer %2d (%s ac97 register 0x%02x), "
233 "left vol:%2d, right vol:%2d:",
234 oss_channel, codec->id ? "Secondary" : "Primary",
235 mh->offset, left, right);
236 #endif
238 if (AC97_STEREO_MASK & (1 << oss_channel)) {
239 /* stereo mixers */
240 if (oss_channel == SOUND_MIXER_IGAIN) {
241 right = (right * mh->scale) / 100;
242 left = (left * mh->scale) / 100;
243 } else {
244 right = ((100 - right) * mh->scale) / 100;
245 left = ((100 - left) * mh->scale) / 100;
247 val = (left << 8) | right;
248 } else if (oss_channel == SOUND_MIXER_SPEAKER) {
249 val = (((100 - left) * mh->scale) / 100) << 1;
250 } else if (oss_channel == SOUND_MIXER_PHONEIN) {
251 val = (((100 - left) * mh->scale) / 100);
252 } else if (oss_channel == SOUND_MIXER_PHONEOUT) {
253 val = (((100 - left) * mh->scale) / 100);
254 } else if (oss_channel == SOUND_MIXER_MIC) {
255 val = codec->codec_read(codec , mh->offset) & ~0x801f;
256 val |= (((100 - left) * mh->scale) / 100);
257 /* the low bit is optional in the tone sliders and masking
258 it lets us avoid the 0xf 'bypass'.. */
259 } else if (oss_channel == SOUND_MIXER_BASS) {
260 val = codec->codec_read(codec , mh->offset) & ~0x0f00;
261 val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
262 } else if (oss_channel == SOUND_MIXER_TREBLE) {
263 val = codec->codec_read(codec , mh->offset) & ~0x000f;
264 val |= (((100 - left) * mh->scale) / 100) & 0x000e;
266 #ifdef DEBUG
267 printk(" 0x%04x", val);
268 #endif
269 codec->codec_write(codec, mh->offset, val);
271 #ifdef DEBUG
272 val = codec->codec_read(codec, mh->offset);
273 printk(" -> 0x%04x\n", val);
274 #endif
277 /* a thin wrapper for write_mixer */
278 static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val )
280 unsigned int left,right;
282 /* cleanse input a little */
283 right = ((val >> 8) & 0xff) ;
284 left = (val & 0xff) ;
286 if (right > 100) right = 100;
287 if (left > 100) left = 100;
289 codec->mixer_state[oss_mixer] = (right << 8) | left;
290 codec->write_mixer(codec, oss_mixer, left, right);
293 /* read or write the recmask, the ac97 can really have left and right recording
294 inputs independantly set, but OSS doesn't seem to want us to express that to
295 the user. the caller guarantees that we have a supported bit set, and they
296 must be holding the card's spinlock */
297 static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask)
299 unsigned int val;
301 if (rw) {
302 /* read it from the card */
303 val = codec->codec_read(codec, 0x1a) & 0x7;
304 return ac97_rm2oss[val];
307 /* else, write the first set in the mask as the
308 output */
310 val = ffs(mask);
311 val = ac97_oss_rm[val-1];
312 val |= val << 8; /* set both channels */
314 #ifdef DEBUG
315 printk("ac97_codec: setting ac97 recmask to 0x%x\n", val);
316 #endif
318 codec->codec_write(codec, 0x1a, val);
320 return 0;
323 static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg)
325 int i, val = 0;
327 if (cmd == SOUND_MIXER_INFO) {
328 mixer_info info;
329 strncpy(info.id, codec->name, sizeof(info.id));
330 strncpy(info.name, codec->name, sizeof(info.name));
331 info.modify_counter = codec->modcnt;
332 if (copy_to_user((void *)arg, &info, sizeof(info)))
333 return -EFAULT;
334 return 0;
336 if (cmd == SOUND_OLD_MIXER_INFO) {
337 _old_mixer_info info;
338 strncpy(info.id, codec->name, sizeof(info.id));
339 strncpy(info.name, codec->name, sizeof(info.name));
340 if (copy_to_user((void *)arg, &info, sizeof(info)))
341 return -EFAULT;
342 return 0;
345 if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
346 return -EINVAL;
348 if (cmd == OSS_GETVERSION)
349 return put_user(SOUND_VERSION, (int *)arg);
351 if (_IOC_DIR(cmd) == _IOC_READ) {
352 switch (_IOC_NR(cmd)) {
353 case SOUND_MIXER_RECSRC: /* give them the current record source */
354 if (!codec->recmask_io) {
355 val = 0;
356 } else {
357 val = codec->recmask_io(codec, 1, 0);
359 break;
361 case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
362 val = codec->supported_mixers;
363 break;
365 case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
366 val = codec->record_sources;
367 break;
369 case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
370 val = codec->stereo_mixers;
371 break;
373 case SOUND_MIXER_CAPS:
374 val = SOUND_CAP_EXCL_INPUT;
375 break;
377 default: /* read a specific mixer */
378 i = _IOC_NR(cmd);
380 if (!supported_mixer(codec, i))
381 return -EINVAL;
383 /* do we ever want to touch the hardware? */
384 val = codec->read_mixer(codec, i);
385 /* val = codec->mixer_state[i]; */
386 break;
388 return put_user(val, (int *)arg);
391 if (_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) {
392 codec->modcnt++;
393 get_user_ret(val, (int *)arg, -EFAULT);
395 switch (_IOC_NR(cmd)) {
396 case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
397 if (!codec->recmask_io) return -EINVAL;
398 if (!(val &= codec->record_sources)) return -EINVAL;
400 codec->recmask_io(codec, 0, val);
402 return 0;
403 default: /* write a specific mixer */
404 i = _IOC_NR(cmd);
406 if (!supported_mixer(codec, i))
407 return -EINVAL;
409 ac97_set_mixer(codec, i, val);
411 return 0;
414 return -EINVAL;
417 /* entry point for /proc/driver/controller_vendor/ac97/%d */
418 int ac97_read_proc (char *page, char **start, off_t off,
419 int count, int *eof, void *data)
421 int len = 0, cap, extid, val, id1, id2;
422 struct ac97_codec *codec;
424 if ((codec = data) == NULL)
425 return -ENODEV;
427 id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
428 id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
429 len += sprintf (page+len, "Vendor name : %s\n", codec->name);
430 len += sprintf (page+len, "Vendor id : %04X %04X\n", id1, id2);
432 extid = codec->codec_read(codec, AC97_EXTENDED_ID);
433 extid &= ~((1<<2)|(1<<4)|(1<<5)|(1<<10)|(1<<11)|(1<<12)|(1<<13));
434 len += sprintf (page+len, "AC97 Version : %s\n",
435 extid ? "2.0 or later" : "1.0");
437 cap = codec->codec_read(codec, AC97_RESET);
438 len += sprintf (page+len, "Capabilities :%s%s%s%s%s%s\n",
439 cap & 0x0001 ? " -dedicated MIC PCM IN channel-" : "",
440 cap & 0x0002 ? " -reserved1-" : "",
441 cap & 0x0004 ? " -bass & treble-" : "",
442 cap & 0x0008 ? " -simulated stereo-" : "",
443 cap & 0x0010 ? " -headphone out-" : "",
444 cap & 0x0020 ? " -loudness-" : "");
445 val = cap & 0x00c0;
446 len += sprintf (page+len, "DAC resolutions :%s%s%s\n",
447 " -16-bit-",
448 val & 0x0040 ? " -18-bit-" : "",
449 val & 0x0080 ? " -20-bit-" : "");
450 val = cap & 0x0300;
451 len += sprintf (page+len, "ADC resolutions :%s%s%s\n",
452 " -16-bit-",
453 val & 0x0100 ? " -18-bit-" : "",
454 val & 0x0200 ? " -20-bit-" : "");
455 len += sprintf (page+len, "3D enhancement : %s\n",
456 ac97_stereo_enhancements[(cap >> 10) & 0x1f]);
458 val = codec->codec_read(codec, AC97_GENERAL_PURPOSE);
459 len += sprintf (page+len, "POP path : %s 3D\n"
460 "Sim. stereo : %s\n"
461 "3D enhancement : %s\n"
462 "Loudness : %s\n"
463 "Mono output : %s\n"
464 "MIC select : %s\n"
465 "ADC/DAC loopback : %s\n",
466 val & 0x8000 ? "post" : "pre",
467 val & 0x4000 ? "on" : "off",
468 val & 0x2000 ? "on" : "off",
469 val & 0x1000 ? "on" : "off",
470 val & 0x0200 ? "MIC" : "MIX",
471 val & 0x0100 ? "MIC2" : "MIC1",
472 val & 0x0080 ? "on" : "off");
474 cap = extid;
475 len += sprintf (page+len, "Ext Capabilities :%s%s%s%s%s%s%s\n",
476 cap & 0x0001 ? " -var rate PCM audio-" : "",
477 cap & 0x0002 ? " -2x PCM audio out-" : "",
478 cap & 0x0008 ? " -var rate MIC in-" : "",
479 cap & 0x0040 ? " -PCM center DAC-" : "",
480 cap & 0x0080 ? " -PCM surround DAC-" : "",
481 cap & 0x0100 ? " -PCM LFE DAC-" : "",
482 cap & 0x0200 ? " -slot/DAC mappings-" : "");
484 return len;
487 int ac97_probe_codec(struct ac97_codec *codec)
489 u16 id1, id2, cap;
490 int i;
492 /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
493 be read zero. Probing of AC97 in this way is not reliable, it is not even SAFE !! */
494 codec->codec_write(codec, AC97_RESET, 0L);
495 if ((cap = codec->codec_read(codec, AC97_RESET)) & 0x8000)
496 return 0;
498 codec->name = NULL;
499 codec->codec_init = NULL;
500 id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
501 id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
502 for (i = 0; i < arraysize(ac97_codec_ids); i++) {
503 if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
504 codec->name = ac97_codec_ids[i].name;
505 codec->codec_init = ac97_codec_ids[i].init;
506 break;
509 if (codec->name == NULL)
510 codec->name = "Unknown";
511 printk(KERN_INFO "ac97_codec: ac97 vendor id1: 0x%04x, id2: 0x%04x (%s)\n",
512 id1, id2, codec->name);
514 /* mixer masks */
515 codec->supported_mixers = AC97_SUPPORTED_MASK;
516 codec->stereo_mixers = AC97_STEREO_MASK;
517 codec->record_sources = AC97_RECORD_MASK;
518 if (!(cap & 0x04))
519 codec->supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE);
521 /* generic OSS to AC97 wrapper */
522 codec->read_mixer = ac97_read_mixer;
523 codec->write_mixer = ac97_write_mixer;
524 codec->recmask_io = ac97_recmask_io;
525 codec->mixer_ioctl = ac97_mixer_ioctl;
527 /* initialize volume level */
528 codec->codec_write(codec, AC97_MASTER_VOL_STEREO, 0L);
529 codec->codec_write(codec, AC97_PCMOUT_VOL, 0L);
531 /* codec specific initialization for 4-6 channel output */
532 if (codec->id != 0 && codec->codec_init != NULL) {
533 codec->codec_init(codec);
536 /* initilize mixer channel volumes */
537 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
538 struct mixer_defaults *md = &mixer_defaults[i];
539 if (md->mixer == -1)
540 break;
541 if (!supported_mixer(codec, md->mixer))
542 continue;
543 ac97_set_mixer(codec, md->mixer, md->value);
546 return 1;
549 static int sigmatel_init(struct ac97_codec * codec)
551 codec->codec_write(codec, AC97_SURROUND_MASTER, 0L);
552 /* initialize SigmaTel STAC9721/23 */
553 codec->codec_write(codec, 0x74, 0x01);
554 return 1;
557 EXPORT_SYMBOL(ac97_read_proc);
558 EXPORT_SYMBOL(ac97_probe_codec);