This source file includes following definitions.
- snd_ac97_proc_read_functions
- snd_ac97_proc_read_main
- snd_ac97_proc_read
- snd_ac97_proc_regs_write
- snd_ac97_proc_regs_read_main
- snd_ac97_proc_regs_read
- snd_ac97_proc_init
- snd_ac97_proc_done
- snd_ac97_bus_proc_init
- snd_ac97_bus_proc_done
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <linux/mutex.h>
  11 
  12 #include <sound/core.h>
  13 #include <sound/ac97_codec.h>
  14 #include <sound/asoundef.h>
  15 #include "ac97_local.h"
  16 #include "ac97_id.h"
  17 
  18 
  19 
  20 
  21 
  22 static void snd_ac97_proc_read_functions(struct snd_ac97 *ac97, struct snd_info_buffer *buffer)
  23 {
  24         int header = 0, function;
  25         unsigned short info, sense_info;
  26         static const char *function_names[12] = {
  27                 "Master Out", "AUX Out", "Center/LFE Out", "SPDIF Out",
  28                 "Phone In", "Mic 1", "Mic 2", "Line In", "CD In", "Video In",
  29                 "Aux In", "Mono Out"
  30         };
  31         static const char *locations[8] = {
  32                 "Rear I/O Panel", "Front Panel", "Motherboard", "Dock/External",
  33                 "reserved", "reserved", "reserved", "NC/unused"
  34         };
  35 
  36         for (function = 0; function < 12; ++function) {
  37                 snd_ac97_write(ac97, AC97_FUNC_SELECT, function << 1);
  38                 info = snd_ac97_read(ac97, AC97_FUNC_INFO);
  39                 if (!(info & 0x0001))
  40                         continue;
  41                 if (!header) {
  42                         snd_iprintf(buffer, "\n                    Gain     Inverted  Buffer delay  Location\n");
  43                         header = 1;
  44                 }
  45                 sense_info = snd_ac97_read(ac97, AC97_SENSE_INFO);
  46                 snd_iprintf(buffer, "%-17s: %3d.%d dBV    %c      %2d/fs         %s\n",
  47                             function_names[function],
  48                             (info & 0x8000 ? -1 : 1) * ((info & 0x7000) >> 12) * 3 / 2,
  49                             ((info & 0x0800) >> 11) * 5,
  50                             info & 0x0400 ? 'X' : '-',
  51                             (info & 0x03e0) >> 5,
  52                             locations[sense_info >> 13]);
  53         }
  54 }
  55 
  56 static const char *snd_ac97_stereo_enhancements[] =
  57 {
  58    "No 3D Stereo Enhancement",
  59    "Analog Devices Phat Stereo",
  60    "Creative Stereo Enhancement",
  61    "National Semi 3D Stereo Enhancement",
  62    "YAMAHA Ymersion",
  63    "BBE 3D Stereo Enhancement",
  64    "Crystal Semi 3D Stereo Enhancement",
  65    "Qsound QXpander",
  66    "Spatializer 3D Stereo Enhancement",
  67    "SRS 3D Stereo Enhancement",
  68    "Platform Tech 3D Stereo Enhancement",
  69    "AKM 3D Audio",
  70    "Aureal Stereo Enhancement",
  71    "Aztech 3D Enhancement",
  72    "Binaura 3D Audio Enhancement",
  73    "ESS Technology Stereo Enhancement",
  74    "Harman International VMAx",
  75    "Nvidea/IC Ensemble/KS Waves 3D Stereo Enhancement",
  76    "Philips Incredible Sound",
  77    "Texas Instruments 3D Stereo Enhancement",
  78    "VLSI Technology 3D Stereo Enhancement",
  79    "TriTech 3D Stereo Enhancement",
  80    "Realtek 3D Stereo Enhancement",
  81    "Samsung 3D Stereo Enhancement",
  82    "Wolfson Microelectronics 3D Enhancement",
  83    "Delta Integration 3D Enhancement",
  84    "SigmaTel 3D Enhancement",
  85    "IC Ensemble/KS Waves",
  86    "Rockwell 3D Stereo Enhancement",
  87    "Reserved 29",
  88    "Reserved 30",
  89    "Reserved 31"
  90 };
  91 
  92 static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx)
  93 {
  94         char name[64];
  95         unsigned short val, tmp, ext, mext;
  96         static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=10/11" };
  97         static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" };
  98         static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };
  99         static const char *double_rate_slots[4] = { "10/11", "7/8", "reserved", "reserved" };
 100 
 101         snd_ac97_get_name(NULL, ac97->id, name, 0);
 102         snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
 103 
 104         if ((ac97->scaps & AC97_SCAP_AUDIO) == 0)
 105                 goto __modem;
 106 
 107         snd_iprintf(buffer, "PCI Subsys Vendor: 0x%04x\n",
 108                     ac97->subsystem_vendor);
 109         snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n",
 110                     ac97->subsystem_device);
 111 
 112         snd_iprintf(buffer, "Flags: %x\n", ac97->flags);
 113 
 114         if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) {
 115                 val = snd_ac97_read(ac97, AC97_INT_PAGING);
 116                 snd_ac97_update_bits(ac97, AC97_INT_PAGING,
 117                                      AC97_PAGE_MASK, AC97_PAGE_1);
 118                 tmp = snd_ac97_read(ac97, AC97_CODEC_CLASS_REV);
 119                 snd_iprintf(buffer, "Revision         : 0x%02x\n", tmp & 0xff);
 120                 snd_iprintf(buffer, "Compat. Class    : 0x%02x\n", (tmp >> 8) & 0x1f);
 121                 snd_iprintf(buffer, "Subsys. Vendor ID: 0x%04x\n",
 122                             snd_ac97_read(ac97, AC97_PCI_SVID));
 123                 snd_iprintf(buffer, "Subsys. ID       : 0x%04x\n\n",
 124                             snd_ac97_read(ac97, AC97_PCI_SID));
 125                 snd_ac97_update_bits(ac97, AC97_INT_PAGING,
 126                                      AC97_PAGE_MASK, val & AC97_PAGE_MASK);
 127         }
 128 
 129         
 130         val = ac97->caps;
 131         snd_iprintf(buffer, "Capabilities     :%s%s%s%s%s%s\n",
 132                     val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" : "",
 133                     val & AC97_BC_RESERVED1 ? " -reserved1-" : "",
 134                     val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",
 135                     val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",
 136                     val & AC97_BC_HEADPHONE ? " -headphone out-" : "",
 137                     val & AC97_BC_LOUDNESS ? " -loudness-" : "");
 138         tmp = ac97->caps & AC97_BC_DAC_MASK;
 139         snd_iprintf(buffer, "DAC resolution   : %s%s%s%s\n",
 140                     tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",
 141                     tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",
 142                     tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",
 143                     tmp == AC97_BC_DAC_MASK ? "???" : "");
 144         tmp = ac97->caps & AC97_BC_ADC_MASK;
 145         snd_iprintf(buffer, "ADC resolution   : %s%s%s%s\n",
 146                     tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",
 147                     tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",
 148                     tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",
 149                     tmp == AC97_BC_ADC_MASK ? "???" : "");
 150         snd_iprintf(buffer, "3D enhancement   : %s\n",
 151                 snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);
 152         snd_iprintf(buffer, "\nCurrent setup\n");
 153         val = snd_ac97_read(ac97, AC97_MIC);
 154         snd_iprintf(buffer, "Mic gain         : %s [%s]\n", val & 0x0040 ? "+20dB" : "+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB");
 155         val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
 156         snd_iprintf(buffer, "POP path         : %s 3D\n"
 157                     "Sim. stereo      : %s\n"
 158                     "3D enhancement   : %s\n"
 159                     "Loudness         : %s\n"
 160                     "Mono output      : %s\n"
 161                     "Mic select       : %s\n"
 162                     "ADC/DAC loopback : %s\n",
 163                     val & 0x8000 ? "post" : "pre",
 164                     val & 0x4000 ? "on" : "off",
 165                     val & 0x2000 ? "on" : "off",
 166                     val & 0x1000 ? "on" : "off",
 167                     val & 0x0200 ? "Mic" : "MIX",
 168                     val & 0x0100 ? "Mic2" : "Mic1",
 169                     val & 0x0080 ? "on" : "off");
 170         if (ac97->ext_id & AC97_EI_DRA)
 171                 snd_iprintf(buffer, "Double rate slots: %s\n",
 172                             double_rate_slots[(val >> 10) & 3]);
 173 
 174         ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
 175         if (ext == 0)
 176                 goto __modem;
 177                 
 178         snd_iprintf(buffer, "Extended ID      : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n",
 179                         (ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,
 180                         (ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,
 181                         ext & AC97_EI_AMAP ? " AMAP" : "",
 182                         ext & AC97_EI_LDAC ? " LDAC" : "",
 183                         ext & AC97_EI_SDAC ? " SDAC" : "",
 184                         ext & AC97_EI_CDAC ? " CDAC" : "",
 185                         (ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,
 186                         ext & AC97_EI_VRM ? " VRM" : "",
 187                         ext & AC97_EI_SPDIF ? " SPDIF" : "",
 188                         ext & AC97_EI_DRA ? " DRA" : "",
 189                         ext & AC97_EI_VRA ? " VRA" : "");
 190         val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
 191         snd_iprintf(buffer, "Extended status  :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
 192                         val & AC97_EA_PRL ? " PRL" : "",
 193                         val & AC97_EA_PRK ? " PRK" : "",
 194                         val & AC97_EA_PRJ ? " PRJ" : "",
 195                         val & AC97_EA_PRI ? " PRI" : "",
 196                         val & AC97_EA_SPCV ? " SPCV" : "",
 197                         val & AC97_EA_MDAC ? " MADC" : "",
 198                         val & AC97_EA_LDAC ? " LDAC" : "",
 199                         val & AC97_EA_SDAC ? " SDAC" : "",
 200                         val & AC97_EA_CDAC ? " CDAC" : "",
 201                         ext & AC97_EI_SPDIF ? spdif_slots[(val & AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",
 202                         val & AC97_EA_VRM ? " VRM" : "",
 203                         val & AC97_EA_SPDIF ? " SPDIF" : "",
 204                         val & AC97_EA_DRA ? " DRA" : "",
 205                         val & AC97_EA_VRA ? " VRA" : "");
 206         if (ext & AC97_EI_VRA) {        
 207                 val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);
 208                 snd_iprintf(buffer, "PCM front DAC    : %iHz\n", val);
 209                 if (ext & AC97_EI_SDAC) {
 210                         val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);
 211                         snd_iprintf(buffer, "PCM Surr DAC     : %iHz\n", val);
 212                 }
 213                 if (ext & AC97_EI_LDAC) {
 214                         val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);
 215                         snd_iprintf(buffer, "PCM LFE DAC      : %iHz\n", val);
 216                 }
 217                 val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);
 218                 snd_iprintf(buffer, "PCM ADC          : %iHz\n", val);
 219         }
 220         if (ext & AC97_EI_VRM) {
 221                 val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);
 222                 snd_iprintf(buffer, "PCM MIC ADC      : %iHz\n", val);
 223         }
 224         if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF) ||
 225             (ac97->id == AC97_ID_YMF743)) {
 226                 if (ac97->flags & AC97_CS_SPDIF)
 227                         val = snd_ac97_read(ac97, AC97_CSR_SPDIF);
 228                 else if (ac97->id == AC97_ID_YMF743) {
 229                         val = snd_ac97_read(ac97, AC97_YMF7X3_DIT_CTRL);
 230                         val = 0x2000 | (val & 0xff00) >> 4 | (val & 0x38) >> 2;
 231                 } else
 232                         val = snd_ac97_read(ac97, AC97_SPDIF);
 233 
 234                 snd_iprintf(buffer, "SPDIF Control    :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",
 235                         val & AC97_SC_PRO ? " PRO" : " Consumer",
 236                         val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",
 237                         val & AC97_SC_COPY ? "" : " Copyright",
 238                         val & AC97_SC_PRE ? " Preemph50/15" : "",
 239                         (val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,
 240                         (val & AC97_SC_L) >> 11,
 241                         (ac97->flags & AC97_CS_SPDIF) ?
 242                             spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT] :
 243                             spdif_rates[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT],
 244                         (ac97->flags & AC97_CS_SPDIF) ?
 245                             (val & AC97_SC_DRS ? " Validity" : "") :
 246                             (val & AC97_SC_DRS ? " DRS" : ""),
 247                         (ac97->flags & AC97_CS_SPDIF) ?
 248                             (val & AC97_SC_V ? " Enabled" : "") :
 249                             (val & AC97_SC_V ? " Validity" : ""));
 250                 
 251                 if ((ac97->id & 0xfffffff0) == 0x414c4720 &&
 252                     (snd_ac97_read(ac97, AC97_ALC650_CLOCK) & 0x01)) {
 253                         val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
 254                         if (val & AC97_ALC650_CLOCK_LOCK) {
 255                                 val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS1);
 256                                 snd_iprintf(buffer, "SPDIF In Status  :%s%s%s%s Category=0x%x Generation=%i",
 257                                             val & AC97_ALC650_PRO ? " PRO" : " Consumer",
 258                                             val & AC97_ALC650_NAUDIO ? " Non-audio" : " PCM",
 259                                             val & AC97_ALC650_COPY ? "" : " Copyright",
 260                                             val & AC97_ALC650_PRE ? " Preemph50/15" : "",
 261                                             (val & AC97_ALC650_CC_MASK) >> AC97_ALC650_CC_SHIFT,
 262                                             (val & AC97_ALC650_L) >> 15);
 263                                 val = snd_ac97_read(ac97, AC97_ALC650_SPDIF_INPUT_STATUS2);
 264                                 snd_iprintf(buffer, "%s Accuracy=%i%s%s\n",
 265                                             spdif_rates[(val & AC97_ALC650_SPSR_MASK) >> AC97_ALC650_SPSR_SHIFT],
 266                                             (val & AC97_ALC650_CLOCK_ACCURACY) >> AC97_ALC650_CLOCK_SHIFT,
 267                                             (val & AC97_ALC650_CLOCK_LOCK ? " Locked" : " Unlocked"),
 268                                             (val & AC97_ALC650_V ? " Validity?" : ""));
 269                         } else {
 270                                 snd_iprintf(buffer, "SPDIF In Status  : Not Locked\n");
 271                         }
 272                 }
 273         }
 274         if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) {
 275                 val = snd_ac97_read(ac97, AC97_INT_PAGING);
 276                 snd_ac97_update_bits(ac97, AC97_INT_PAGING,
 277                                      AC97_PAGE_MASK, AC97_PAGE_1);
 278                 snd_ac97_proc_read_functions(ac97, buffer);
 279                 snd_ac97_update_bits(ac97, AC97_INT_PAGING,
 280                                      AC97_PAGE_MASK, val & AC97_PAGE_MASK);
 281         }
 282 
 283 
 284       __modem:
 285         mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);
 286         if (mext == 0)
 287                 return;
 288         
 289         snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n",
 290                         (mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,
 291                         mext & AC97_MEI_CID2 ? " CID2" : "",
 292                         mext & AC97_MEI_CID1 ? " CID1" : "",
 293                         mext & AC97_MEI_HANDSET ? " HSET" : "",
 294                         mext & AC97_MEI_LINE2 ? " LIN2" : "",
 295                         mext & AC97_MEI_LINE1 ? " LIN1" : "");
 296         val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS);
 297         snd_iprintf(buffer, "Modem status     :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
 298                         val & AC97_MEA_GPIO ? " GPIO" : "",
 299                         val & AC97_MEA_MREF ? " MREF" : "",
 300                         val & AC97_MEA_ADC1 ? " ADC1" : "",
 301                         val & AC97_MEA_DAC1 ? " DAC1" : "",
 302                         val & AC97_MEA_ADC2 ? " ADC2" : "",
 303                         val & AC97_MEA_DAC2 ? " DAC2" : "",
 304                         val & AC97_MEA_HADC ? " HADC" : "",
 305                         val & AC97_MEA_HDAC ? " HDAC" : "",
 306                         val & AC97_MEA_PRA ? " PRA(GPIO)" : "",
 307                         val & AC97_MEA_PRB ? " PRB(res)" : "",
 308                         val & AC97_MEA_PRC ? " PRC(ADC1)" : "",
 309                         val & AC97_MEA_PRD ? " PRD(DAC1)" : "",
 310                         val & AC97_MEA_PRE ? " PRE(ADC2)" : "",
 311                         val & AC97_MEA_PRF ? " PRF(DAC2)" : "",
 312                         val & AC97_MEA_PRG ? " PRG(HADC)" : "",
 313                         val & AC97_MEA_PRH ? " PRH(HDAC)" : "");
 314         if (mext & AC97_MEI_LINE1) {
 315                 val = snd_ac97_read(ac97, AC97_LINE1_RATE);
 316                 snd_iprintf(buffer, "Line1 rate       : %iHz\n", val);
 317         }
 318         if (mext & AC97_MEI_LINE2) {
 319                 val = snd_ac97_read(ac97, AC97_LINE2_RATE);
 320                 snd_iprintf(buffer, "Line2 rate       : %iHz\n", val);
 321         }
 322         if (mext & AC97_MEI_HANDSET) {
 323                 val = snd_ac97_read(ac97, AC97_HANDSET_RATE);
 324                 snd_iprintf(buffer, "Headset rate     : %iHz\n", val);
 325         }
 326 }
 327 
 328 static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 329 {
 330         struct snd_ac97 *ac97 = entry->private_data;
 331         
 332         mutex_lock(&ac97->page_mutex);
 333         if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {        
 334                 int idx;
 335                 for (idx = 0; idx < 3; idx++)
 336                         if (ac97->spec.ad18xx.id[idx]) {
 337                                 
 338                                 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
 339                                                      ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
 340                                 snd_ac97_proc_read_main(ac97, buffer, idx);
 341                                 snd_iprintf(buffer, "\n\n");
 342                         }
 343                 
 344                 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
 345                 
 346                 snd_iprintf(buffer, "\nAD18XX configuration\n");
 347                 snd_iprintf(buffer, "Unchained        : 0x%04x,0x%04x,0x%04x\n",
 348                         ac97->spec.ad18xx.unchained[0],
 349                         ac97->spec.ad18xx.unchained[1],
 350                         ac97->spec.ad18xx.unchained[2]);
 351                 snd_iprintf(buffer, "Chained          : 0x%04x,0x%04x,0x%04x\n",
 352                         ac97->spec.ad18xx.chained[0],
 353                         ac97->spec.ad18xx.chained[1],
 354                         ac97->spec.ad18xx.chained[2]);
 355         } else {
 356                 snd_ac97_proc_read_main(ac97, buffer, 0);
 357         }
 358         mutex_unlock(&ac97->page_mutex);
 359 }
 360 
 361 #ifdef CONFIG_SND_DEBUG
 362 
 363 static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 364 {
 365         struct snd_ac97 *ac97 = entry->private_data;
 366         char line[64];
 367         unsigned int reg, val;
 368         mutex_lock(&ac97->page_mutex);
 369         while (!snd_info_get_line(buffer, line, sizeof(line))) {
 370                 if (sscanf(line, "%x %x", ®, &val) != 2)
 371                         continue;
 372                 
 373                 if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
 374                         snd_ac97_write_cache(ac97, reg, val);
 375         }
 376         mutex_unlock(&ac97->page_mutex);
 377 }
 378 #endif
 379 
 380 static void snd_ac97_proc_regs_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx)
 381 {
 382         int reg, val;
 383 
 384         for (reg = 0; reg < 0x80; reg += 2) {
 385                 val = snd_ac97_read(ac97, reg);
 386                 snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);
 387         }
 388 }
 389 
 390 static void snd_ac97_proc_regs_read(struct snd_info_entry *entry, 
 391                                     struct snd_info_buffer *buffer)
 392 {
 393         struct snd_ac97 *ac97 = entry->private_data;
 394 
 395         mutex_lock(&ac97->page_mutex);
 396         if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {        
 397 
 398                 int idx;
 399                 for (idx = 0; idx < 3; idx++)
 400                         if (ac97->spec.ad18xx.id[idx]) {
 401                                 
 402                                 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
 403                                                      ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
 404                                 snd_ac97_proc_regs_read_main(ac97, buffer, idx);
 405                         }
 406                 
 407                 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
 408         } else {
 409                 snd_ac97_proc_regs_read_main(ac97, buffer, 0);
 410         }       
 411         mutex_unlock(&ac97->page_mutex);
 412 }
 413 
 414 void snd_ac97_proc_init(struct snd_ac97 * ac97)
 415 {
 416         struct snd_info_entry *entry;
 417         char name[32];
 418         const char *prefix;
 419 
 420         if (ac97->bus->proc == NULL)
 421                 return;
 422         prefix = ac97_is_audio(ac97) ? "ac97" : "mc97";
 423         sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
 424         entry = snd_info_create_card_entry(ac97->bus->card, name,
 425                                            ac97->bus->proc);
 426         if (entry)
 427                 snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
 428         ac97->proc = entry;
 429         sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num);
 430         entry = snd_info_create_card_entry(ac97->bus->card, name,
 431                                            ac97->bus->proc);
 432         if (entry) {
 433                 snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
 434 #ifdef CONFIG_SND_DEBUG
 435                 entry->mode |= 0200;
 436                 entry->c.text.write = snd_ac97_proc_regs_write;
 437 #endif
 438         }
 439         ac97->proc_regs = entry;
 440 }
 441 
 442 void snd_ac97_proc_done(struct snd_ac97 * ac97)
 443 {
 444         snd_info_free_entry(ac97->proc_regs);
 445         ac97->proc_regs = NULL;
 446         snd_info_free_entry(ac97->proc);
 447         ac97->proc = NULL;
 448 }
 449 
 450 void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus)
 451 {
 452         struct snd_info_entry *entry;
 453         char name[32];
 454 
 455         sprintf(name, "codec97#%d", bus->num);
 456         entry = snd_info_create_card_entry(bus->card, name,
 457                                            bus->card->proc_root);
 458         if (entry)
 459                 entry->mode = S_IFDIR | 0555;
 460         bus->proc = entry;
 461 }
 462 
 463 void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus)
 464 {
 465         snd_info_free_entry(bus->proc);
 466         bus->proc = NULL;
 467 }