/[openvortex]/alsa/alsa-kernel/pci/ac97/ac97_codec.c
ViewVC logotype

Diff of /alsa/alsa-kernel/pci/ac97/ac97_codec.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by vizard, Sun Jun 15 21:01:31 2003 UTC revision 1.4 by vizard, Mon Aug 11 00:06:39 2003 UTC
# Line 32  Line 32 
32  #include <sound/ac97_codec.h>  #include <sound/ac97_codec.h>
33  #include <sound/asoundef.h>  #include <sound/asoundef.h>
34  #include <sound/initval.h>  #include <sound/initval.h>
35    #include "ac97_local.h"
36  #include "ac97_id.h"  #include "ac97_id.h"
37  #include "ac97_patch.h"  #include "ac97_patch.h"
38    
# Line 51  MODULE_PARM_SYNTAX(enable_loopback, SNDR Line 52  MODULE_PARM_SYNTAX(enable_loopback, SNDR
52    
53   */   */
54    
 static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix);  
   
55  typedef struct {  typedef struct {
56          unsigned int id;          unsigned int id;
57          unsigned int mask;          unsigned int mask;
# Line 114  static const ac97_codec_id_t snd_ac97_co Line 113  static const ac97_codec_id_t snd_ac97_co
113  { 0x414c4740, 0xfffffff0, "ALC202",             NULL,           NULL },  { 0x414c4740, 0xfffffff0, "ALC202",             NULL,           NULL },
114  { 0x414c4750, 0xfffffff0, "ALC250",             NULL,           NULL },  { 0x414c4750, 0xfffffff0, "ALC250",             NULL,           NULL },
115  { 0x414c4770, 0xfffffff0, "ALC203",             NULL,           NULL },  { 0x414c4770, 0xfffffff0, "ALC203",             NULL,           NULL },
116  { 0x434d4941, 0xffffffff, "CMI9738",            NULL,           NULL },  { 0x434d4941, 0xffffffff, "CMI9738",            patch_cm9738,   NULL },
117  { 0x434d4961, 0xffffffff, "CMI9739",            patch_cm9739,   NULL },  { 0x434d4961, 0xffffffff, "CMI9739",            patch_cm9739,   NULL },
118  { 0x43525900, 0xfffffff8, "CS4297",             NULL,           NULL },  { 0x43525900, 0xfffffff8, "CS4297",             NULL,           NULL },
119  { 0x43525910, 0xfffffff8, "CS4297A",            patch_cirrus_spdif,     NULL },  { 0x43525910, 0xfffffff8, "CS4297A",            patch_cirrus_spdif,     NULL },
# Line 134  static const ac97_codec_id_t snd_ac97_co Line 133  static const ac97_codec_id_t snd_ac97_co
133  { 0x49434501, 0xffffffff, "ICE1230",            NULL,           NULL },  { 0x49434501, 0xffffffff, "ICE1230",            NULL,           NULL },
134  { 0x49434511, 0xffffffff, "ICE1232",            NULL,           NULL }, // alias VIA VT1611A?  { 0x49434511, 0xffffffff, "ICE1232",            NULL,           NULL }, // alias VIA VT1611A?
135  { 0x49434514, 0xffffffff, "ICE1232A",           NULL,           NULL },  { 0x49434514, 0xffffffff, "ICE1232A",           NULL,           NULL },
136  { 0x49434551, 0xffffffff, "VT1616",             NULL,           NULL },  { 0x49434551, 0xffffffff, "VT1616",             patch_vt1616,   NULL },
137  { 0x49434552, 0xffffffff, "VT1616i",            NULL,           NULL }, // VT1616 compatible (chipset integrated)  { 0x49434552, 0xffffffff, "VT1616i",            patch_vt1616,   NULL }, // VT1616 compatible (chipset integrated)
138  { 0x49544520, 0xffffffff, "IT2226E",            NULL,           NULL },  { 0x49544520, 0xffffffff, "IT2226E",            NULL,           NULL },
139  { 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL,           NULL }, // only guess --jk  { 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL,           NULL }, // only guess --jk
140  { 0x4e534331, 0xffffffff, "LM4549",             NULL,           NULL },  { 0x4e534331, 0xffffffff, "LM4549",             NULL,           NULL },
# Line 158  static const ac97_codec_id_t snd_ac97_co Line 157  static const ac97_codec_id_t snd_ac97_co
157  { 0x594d4800, 0xffffffff, "YMF743",             NULL,           NULL },  { 0x594d4800, 0xffffffff, "YMF743",             NULL,           NULL },
158  { 0x594d4802, 0xffffffff, "YMF752",             NULL,           NULL },  { 0x594d4802, 0xffffffff, "YMF752",             NULL,           NULL },
159  { 0x594d4803, 0xffffffff, "YMF753",             patch_yamaha_ymf753,    NULL },  { 0x594d4803, 0xffffffff, "YMF753",             patch_yamaha_ymf753,    NULL },
160  { 0x83847600, 0xffffffff, "STAC9700/83/84",     NULL,           NULL },  { 0x83847600, 0xffffffff, "STAC9700/83/84",     patch_sigmatel_stac9700,        NULL },
161  { 0x83847604, 0xffffffff, "STAC9701/3/4/5",     NULL,           NULL },  { 0x83847604, 0xffffffff, "STAC9701/3/4/5",     NULL,           NULL },
162  { 0x83847605, 0xffffffff, "STAC9704",           NULL,           NULL },  { 0x83847605, 0xffffffff, "STAC9704",           NULL,           NULL },
163  { 0x83847608, 0xffffffff, "STAC9708/11",        patch_sigmatel_stac9708,        NULL },  { 0x83847608, 0xffffffff, "STAC9708/11",        patch_sigmatel_stac9708,        NULL },
# Line 171  static const ac97_codec_id_t snd_ac97_co Line 170  static const ac97_codec_id_t snd_ac97_co
170  { 0,          0,          NULL,                 NULL,           NULL }  { 0,          0,          NULL,                 NULL,           NULL }
171  };  };
172    
173  static const char *snd_ac97_stereo_enhancements[] =  const char *snd_ac97_stereo_enhancements[] =
174  {  {
175    /*   0 */ "No 3D Stereo Enhancement",    /*   0 */ "No 3D Stereo Enhancement",
176    /*   1 */ "Analog Devices Phat Stereo",    /*   1 */ "Analog Devices Phat Stereo",
# Line 310  void snd_ac97_write_cache(ac97_t *ac97, Line 309  void snd_ac97_write_cache(ac97_t *ac97,
309          set_bit(reg, ac97->reg_accessed);          set_bit(reg, ac97->reg_accessed);
310  }  }
311    
 static void snd_ac97_write_cache_test(ac97_t *ac97, unsigned short reg, unsigned short value)  
 {  
 #if 0  
         if (!snd_ac97_valid_reg(ac97, reg))  
                 return;  
         //spin_lock(&ac97->reg_lock);  
         ac97->write(ac97, reg, value);  
         ac97->regs[reg] = ac97->read(ac97, reg);  
         if (value != ac97->regs[reg])  
                 snd_printk("AC97 reg=%02x val=%04x real=%04x\n", reg, value, ac97->regs[reg]);  
         //spin_unlock(&ac97->reg_lock);  
 #endif  
         snd_ac97_write_cache(ac97, reg, value);  
 }  
   
312  /**  /**
313   * snd_ac97_update - update the value on the given register   * snd_ac97_update - update the value on the given register
314   * @ac97: the ac97 instance   * @ac97: the ac97 instance
# Line 518  static int snd_ac97_put_enum_double(snd_ Line 502  static int snd_ac97_put_enum_double(snd_
502          return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift);          return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift);
503  }  }
504    
505  #define AC97_SINGLE(xname, reg, shift, mask, invert) \  int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \  
   .get = snd_ac97_get_single, .put = snd_ac97_put_single, \  
   .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }  
   
 static int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)  
506  {  {
507          int mask = (kcontrol->private_value >> 16) & 0xff;          int mask = (kcontrol->private_value >> 16) & 0xff;
508    
# Line 534  static int snd_ac97_info_single(snd_kcon Line 513  static int snd_ac97_info_single(snd_kcon
513          return 0;          return 0;
514  }  }
515    
516  static int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
517  {  {
518          ac97_t *ac97 = snd_kcontrol_chip(kcontrol);          ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
519          int reg = kcontrol->private_value & 0xff;          int reg = kcontrol->private_value & 0xff;
# Line 548  static int snd_ac97_get_single(snd_kcont Line 527  static int snd_ac97_get_single(snd_kcont
527          return 0;          return 0;
528  }  }
529    
530  static int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
531  {  {
532          ac97_t *ac97 = snd_kcontrol_chip(kcontrol);          ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
533          int reg = kcontrol->private_value & 0xff;          int reg = kcontrol->private_value & 0xff;
# Line 718  AC97_ENUM_DOUBLE("Mic Select", AC97_GENE Line 697  AC97_ENUM_DOUBLE("Mic Select", AC97_GENE
697  AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)  AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
698  };  };
699    
700  static const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {  const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {
701  AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),  AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),
702  AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)  AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)
703  };  };
# Line 743  AC97_SINGLE("Sigmatel Surround Playback Line 722  AC97_SINGLE("Sigmatel Surround Playback
722  AC97_DOUBLE("Sigmatel Surround Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)  AC97_DOUBLE("Sigmatel Surround Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)
723  };  };
724    
 static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {  
 AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),  
 AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)  
 };  
   
725  static const snd_kcontrol_new_t snd_ac97_control_eapd =  static const snd_kcontrol_new_t snd_ac97_control_eapd =
726  AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);  AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);
727    
 static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {  
 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),  
 AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),  
 AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),  
 AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),  
 };  
   
728  static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)  static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
729  {  {
730          uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;          uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
# Line 892  static int snd_ac97_put_spsa(snd_kcontro Line 859  static int snd_ac97_put_spsa(snd_kcontro
859          return 0;          return 0;
860  }  }
861    
862  static const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {  const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
863          {          {
864                  .access = SNDRV_CTL_ELEM_ACCESS_READ,                  .access = SNDRV_CTL_ELEM_ACCESS_READ,
865                  .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                  .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
# Line 916  static const snd_kcontrol_new_t snd_ac97 Line 883  static const snd_kcontrol_new_t snd_ac97
883          },          },
884    
885          AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),AC97_EXTENDED_STATUS, 2, 1, 0),          AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),AC97_EXTENDED_STATUS, 2, 1, 0),
         // AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",AC97_EXTENDED_STATUS, 4, 3, 0)  
886          {          {
887                  .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                  .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
888                  .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",                  .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA",
# Line 927  static const snd_kcontrol_new_t snd_ac97 Line 893  static const snd_kcontrol_new_t snd_ac97
893          },          },
894  };  };
895    
 static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {  
     AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),  
     AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)  
 };  
   
 static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[2] = {  
     AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),  
 };  
   
896  #define AD18XX_PCM_BITS(xname, codec, shift, mask) \  #define AD18XX_PCM_BITS(xname, codec, shift, mask) \
897  { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \  { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \
898    .get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \    .get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \
# Line 1031  static const snd_kcontrol_new_t snd_ac97 Line 988  static const snd_kcontrol_new_t snd_ac97
988  AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31)  AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31)
989  };  };
990    
 static int snd_ac97_ad1980_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)  
 {  
         static char *texts[2] = { "AC-Link", "A/D Converter" };  
   
         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;  
         uinfo->count = 1;  
         uinfo->value.enumerated.items = 2;  
         if (uinfo->value.enumerated.item > 1)  
                 uinfo->value.enumerated.item = 1;  
         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);  
         return 0;  
 }  
   
 static int snd_ac97_ad1980_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         val = ac97->regs[AC97_AD_SERIAL_CFG];  
         ucontrol->value.enumerated.item[0] = (val >> 2) & 1;  
         return 0;  
 }  
   
 static int snd_ac97_ad1980_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         if (ucontrol->value.enumerated.item[0] > 1)  
                 return -EINVAL;  
         val = ucontrol->value.enumerated.item[0] << 2;  
         return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);  
 }  
   
 static const snd_kcontrol_new_t snd_ac97_ad1980_spdif_source = {  
         .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,  
         .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",  
         .info   = snd_ac97_ad1980_spdif_source_info,  
         .get    = snd_ac97_ad1980_spdif_source_get,  
         .put    = snd_ac97_ad1980_spdif_source_put,  
 };  
   
 /*  
  * ALC650  
  */  
 static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {  
         AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),  
         AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),  
         AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),  
         AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),  
         /* 4: Analog Input To Surround */  
         /* 5: Analog Input To Center/LFE */  
         /* 6: Independent Master Volume Right */  
         /* 7: Independent Master Volume Left */  
         /* 8: reserved */  
         AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),  
         AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),  
 #if 0 /* always set in patch_alc650 */  
         AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),  
         AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),  
         AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),  
         AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),  
         AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),  
         AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),  
 #endif  
 };  
   
 static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =  
 AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);  
   
   
 static int snd_ac97_alc650_mic_gpio_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;  
         return 0;  
 }  
   
 static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         int change;  
         change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,  
                                       ucontrol->value.integer.value[0] ? (1 << 10) : 0);  
         if (change) {  
                 /* GPIO0 write for mic */  
                 snd_ac97_update_bits(ac97, 0x76, 0x01,  
                                      ucontrol->value.integer.value[0] ? 0 : 0x01);  
                 /* GPIO0 high for mic */  
                 snd_ac97_update_bits(ac97, 0x78, 0x100,  
                                      ucontrol->value.integer.value[0] ? 0 : 0x100);  
         }  
         return change;  
 }  
   
 static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {  
         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,  
         .name = "Mic As Center/LFE",  
         .info = snd_ac97_info_single,  
         .get = snd_ac97_alc650_mic_gpio_get,  
         .put = snd_ac97_alc650_mic_gpio_put,  
         .private_value = (1 << 16), /* for info */  
 };  
   
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {  
         AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),  
         AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),  
         AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),  
 };  
   
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */  
   
 /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */  
 static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)  
 {  
         static char *texts[3] = {  
                 "Standard", "Small", "Smaller"  
         };  
   
         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;  
         uinfo->count = 1;  
         uinfo->value.enumerated.items = 3;  
         if (uinfo->value.enumerated.item > 2)  
                 uinfo->value.enumerated.item = 2;  
         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);  
         return 0;  
 }  
   
 static int snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         val = ac97->regs[AC97_YMF753_3D_MODE_SEL];  
         val = (val >> 10) & 3;  
         if (val > 0)    /* 0 = invalid */  
                 val--;  
         ucontrol->value.enumerated.item[0] = val;  
         return 0;  
 }  
   
 static int snd_ac97_ymf753_put_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         if (ucontrol->value.enumerated.item[0] > 2)  
                 return -EINVAL;  
         val = (ucontrol->value.enumerated.item[0] + 1) << 10;  
         return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);  
 }  
   
 static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =  
 {  
         .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,  
         .name   = "3D Control - Speaker",  
         .info   = snd_ac97_ymf753_info_speaker,  
         .get    = snd_ac97_ymf753_get_speaker,  
         .put    = snd_ac97_ymf753_put_speaker,  
 };  
   
 /* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */  
 static int snd_ac97_ymf753_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)  
 {  
         static char *texts[2] = { "AC-Link", "A/D Converter" };  
   
         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;  
         uinfo->count = 1;  
         uinfo->value.enumerated.items = 2;  
         if (uinfo->value.enumerated.item > 1)  
                 uinfo->value.enumerated.item = 1;  
         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);  
         return 0;  
 }  
   
 static int snd_ac97_ymf753_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         val = ac97->regs[AC97_YMF753_DIT_CTRL2];  
         ucontrol->value.enumerated.item[0] = (val >> 1) & 1;  
         return 0;  
 }  
   
 static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         if (ucontrol->value.enumerated.item[0] > 1)  
                 return -EINVAL;  
         val = ucontrol->value.enumerated.item[0] << 1;  
         return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);  
 }  
   
 /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.  
    The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.  
    By default, no output pin is selected, and the S/PDIF signal is not output.  
    There is also a bit to mute S/PDIF output in a vendor-specific register. */  
 static int snd_ac97_ymf753_spdif_output_pin_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)  
 {  
         static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };  
   
         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;  
         uinfo->count = 1;  
         uinfo->value.enumerated.items = 3;  
         if (uinfo->value.enumerated.item > 2)  
                 uinfo->value.enumerated.item = 2;  
         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);  
         return 0;  
 }  
   
 static int snd_ac97_ymf753_spdif_output_pin_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         val = ac97->regs[AC97_YMF753_DIT_CTRL2];  
         ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;  
         return 0;  
 }  
   
 static int snd_ac97_ymf753_spdif_output_pin_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         if (ucontrol->value.enumerated.item[0] > 2)  
                 return -EINVAL;  
         val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :  
               (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;  
         return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);  
         /* The following can be used to direct S/PDIF output to pin 47 (EAPD).  
            snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */  
 }  
   
 static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {  
         {  
                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,  
                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",  
                 .info   = snd_ac97_ymf753_spdif_source_info,  
                 .get    = snd_ac97_ymf753_spdif_source_get,  
                 .put    = snd_ac97_ymf753_spdif_source_put,  
         },  
         {  
                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,  
                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",  
                 .info   = snd_ac97_ymf753_spdif_output_pin_info,  
                 .get    = snd_ac97_ymf753_spdif_output_pin_get,  
                 .put    = snd_ac97_ymf753_spdif_output_pin_put,  
         },  
         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1)  
 };  
   
   
 /*  
  * C-Media codecs  
  */  
   
 static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)  
 {  
         static char *texts[] = { "Analog", "Digital" };  
   
         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;  
         uinfo->count = 1;  
         uinfo->value.enumerated.items = 2;  
         if (uinfo->value.enumerated.item > 1)  
                 uinfo->value.enumerated.item = 1;  
         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);  
         return 0;  
 }  
   
 static int snd_ac97_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
         unsigned short val;  
   
         val = ac97->regs[AC97_CM9739_SPDIF_CTRL];  
         ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;  
         return 0;  
 }  
   
 static int snd_ac97_cmedia_spdif_playback_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)  
 {  
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);  
   
         return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,  
                                     0x01 << 1,  
                                     (ucontrol->value.enumerated.item[0] & 0x01) << 1);  
 }  
   
 static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {  
         /* BIT 0: SPDI_EN - always true */  
         { /* BIT 1: SPDIFS */  
                 .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,  
                 .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",  
                 .info   = snd_ac97_cmedia_spdif_playback_source_info,  
                 .get    = snd_ac97_cmedia_spdif_playback_source_get,  
                 .put    = snd_ac97_cmedia_spdif_playback_source_put,  
         },  
         /* BIT 2: IG_SPIV */  
         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),  
         /* BIT 3: SPI2F */  
         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),  
         /* BIT 4: SPI2SDI */  
         AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),  
         /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */  
 };  
   
 static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {  
         AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),  
 };  
   
 static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {  
         AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),  
         AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),  
 };  
   
991  /*  /*
992   *   *
993   */   */
# Line 1414  static int snd_ac97_try_volume_mix(ac97_ Line 1052  static int snd_ac97_try_volume_mix(ac97_
1052          if (!(val & mask)) {          if (!(val & mask)) {
1053                  /* nothing seems to be here - mute flag is not set */                  /* nothing seems to be here - mute flag is not set */
1054                  /* try another test */                  /* try another test */
1055                  snd_ac97_write_cache_test(ac97, reg, val | mask);                  snd_ac97_write_cache(ac97, reg, val | mask);
1056                  val = snd_ac97_read(ac97, reg);                  val = snd_ac97_read(ac97, reg);
1057                  if (!(val & mask))                  if (!(val & mask))
1058                          return 0;       /* nothing here */                          return 0;       /* nothing here */
# Line 1422  static int snd_ac97_try_volume_mix(ac97_ Line 1060  static int snd_ac97_try_volume_mix(ac97_
1060          return 1;               /* success, useable */          return 1;               /* success, useable */
1061  }  }
1062    
1063  static int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)  int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)
1064  {  {
1065          unsigned short mask, val, orig, res;          unsigned short mask, val, orig, res;
1066    
# Line 1491  static inline int printable(unsigned int Line 1129  static inline int printable(unsigned int
1129          return x;          return x;
1130  }  }
1131    
1132  static snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97)  snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97)
1133  {  {
1134          snd_kcontrol_new_t template;          snd_kcontrol_new_t template;
1135          memcpy(&template, _template, sizeof(template));          memcpy(&template, _template, sizeof(template));
# Line 1500  static snd_kcontrol_t *snd_ac97_cnew(con Line 1138  static snd_kcontrol_t *snd_ac97_cnew(con
1138          return snd_ctl_new1(&template, ac97);          return snd_ctl_new1(&template, ac97);
1139  }  }
1140    
1141  static int snd_ac97_mixer_build(snd_card_t * card, ac97_t * ac97)  static int snd_ac97_mixer_build(ac97_t * ac97)
1142  {  {
1143            snd_card_t *card = ac97->card;
1144          snd_kcontrol_t *kctl;          snd_kcontrol_t *kctl;
1145          const snd_kcontrol_new_t *knew;          const snd_kcontrol_new_t *knew;
1146          int err;          int err;
# Line 1679  static int snd_ac97_mixer_build(snd_card Line 1318  static int snd_ac97_mixer_build(snd_card
1318                          ac97->spec.ad18xx.pcmreg[2] = 0x9f1f;                          ac97->spec.ad18xx.pcmreg[2] = 0x9f1f;
1319                  }                  }
1320          } else {          } else {
1321                    unsigned int pcm_ctrls = 2;
1322                  /* FIXME: C-Media chips have no PCM volume!! */                  /* FIXME: C-Media chips have no PCM volume!! */
1323                  if (/*ac97->id == 0x434d4941 ||*/                  if (/*ac97->id == 0x434d4941 ||*/
1324                      ac97->id == 0x434d4942 ||                      ac97->id == 0x434d4942 ||
1325                      ac97->id == 0x434d4961)                      ac97->id == 0x434d4961)
1326                          goto no_pcm;                          pcm_ctrls = 1;
1327                  for (idx = 0; idx < 2; idx++)                  for (idx = 0; idx < pcm_ctrls; idx++)
1328                          if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pcm[idx], ac97))) < 0)                          if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pcm[idx], ac97))) < 0)
1329                                  return err;                                  return err;
1330          }          }
1331          snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);          snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
1332    
  no_pcm:  
1333          /* build Capture controls */          /* build Capture controls */
1334          for (idx = 0; idx < 3; idx++)          for (idx = 0; idx < 3; idx++)
1335                  if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_capture[idx], ac97))) < 0)                  if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_capture[idx], ac97))) < 0)
# Line 1751  static int snd_ac97_mixer_build(snd_card Line 1390  static int snd_ac97_mixer_build(snd_card
1390          snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x0000);          snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x0000);
1391    
1392          /* build 3D controls */          /* build 3D controls */
1393          switch (ac97->id) {          if (ac97->build_ops && ac97->build_ops->build_3d) {
1394          case AC97_ID_STAC9708:                  ac97->build_ops->build_3d(ac97);
1395                  if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)          } else {
                         return err;  
                 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");  
                 kctl->private_value = AC97_3D_CONTROL | (3 << 16);  
                 if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)  
                         return err;  
                 strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");  
                 kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);  
                 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);  
                 break;  
         case AC97_ID_STAC9700:  
         case AC97_ID_STAC9721:  
         case AC97_ID_STAC9744:  
         case AC97_ID_STAC9756:  
                 if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)  
                         return err;  
                 strcpy(kctl->id.name, "3D Control Sigmatel - Depth");  
                 kctl->private_value = AC97_3D_CONTROL | (3 << 16);  
                 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);  
                 break;  
         case AC97_ID_YMF753:  
                 if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)  
                         return err;  
                 strcpy(kctl->id.name, "3D Control - Wide");  
                 kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);  
                 snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);  
                 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)  
                         return err;  
                 snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);  
                 break;  
         default:  
1396                  if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) {                  if (snd_ac97_try_volume_mix(ac97, AC97_3D_CONTROL)) {
1397                          unsigned short val;                          unsigned short val;
1398                          val = 0x0707;                          val = 0x0707;
# Line 1801  static int snd_ac97_mixer_build(snd_card Line 1410  static int snd_ac97_mixer_build(snd_card
1410                          snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);                          snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
1411                  }                  }
1412          }          }
1413            
1414          /* build S/PDIF controls */          /* build S/PDIF controls */
1415          if (ac97->ext_id & AC97_EI_SPDIF) {          if (ac97->ext_id & AC97_EI_SPDIF) {
1416                  if (ac97->flags & AC97_CS_SPDIF) {                  if (ac97->build_ops && ac97->build_ops->build_spdif) {
1417                          for (idx = 0; idx < 3; idx++)                          if ((err = ac97->build_ops->build_spdif(ac97)) < 0)
                                 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)  
                                         return err;  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cirrus_controls_spdif[0], ac97))) < 0)  
1418                                  return err;                                  return err;
                         switch (ac97->id & AC97_ID_CS_MASK) {  
                         case AC97_ID_CS4205:  
                                 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cirrus_controls_spdif[1], ac97))) < 0)  
                                         return err;  
                                 break;  
                         }  
                         /* set default PCM S/PDIF params */  
                         /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */  
                         snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);  
                 } else if (ac97->flags & AC97_CX_SPDIF) {  
                         for (idx = 0; idx < 3; idx++)  
                                 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)  
                                         return err;  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_conexant_controls_spdif[0], ac97))) < 0)  
                                 return err;  
                         /* set default PCM S/PDIF params */  
                         /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */  
                         snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,  
                                              snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));  
                           
1419                  } else {                  } else {
1420                          for (idx = 0; idx < 5; idx++)                          for (idx = 0; idx < 5; idx++)
1421                                  if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)                                  if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0)
1422                                          return err;                                          return err;
1423                          switch (ac97->id) {                          if (ac97->build_ops && ac97->build_ops->build_post_spdif) {
1424                          case AC97_ID_YMF753:                                  if ((err = ac97->build_ops->build_post_spdif(ac97)) < 0)
                                 for (idx = 0; idx < 3; idx++)  
                                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_ymf753_controls_spdif[idx], ac97))) < 0)  
                                                 return err;  
                                 break;  
                         case AC97_ID_AD1980:  
                                 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_ad1980_spdif_source, ac97))) < 0)  
1425                                          return err;                                          return err;
                                 break;  
                         case AC97_ID_CM9739:  
                                 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_cm9739_controls_spdif); idx++)  
                                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cm9739_controls_spdif[idx], ac97))) < 0)  
                                                 return err;  
                                 break;  
1426                          }                          }
1427                          /* set default PCM S/PDIF params */                          /* set default PCM S/PDIF params */
1428                          /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */                          /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
1429                          snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);                          snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);
1430                  }                  }
   
1431                  ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;                  ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
1432          }          }
1433                    
1434          /* build chip specific controls */          /* build chip specific controls */
1435          switch (ac97->id) {          if (ac97->build_ops && ac97->build_ops->build_specific)
1436          case AC97_ID_STAC9700:                  if ((err = ac97->build_ops->build_specific(ac97)) < 0)
1437          case AC97_ID_STAC9708:                          return err;
         case AC97_ID_STAC9721:  
         case AC97_ID_STAC9744:  
         case AC97_ID_STAC9756:  
                 snd_ac97_write_cache_test(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);  
                 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_sigmatel_controls[0], ac97))) < 0)  
                                 return err;  
                 if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_sigmatel_controls[1], ac97))) < 0)  
                                 return err;  
                 break;  
         case AC97_ID_ALC650:  
                 /* detect ALC650 rev.E of later */  
                 for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_alc650); idx++)  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_alc650[idx], ac97))) < 0)  
                                 return err;  
                 if ((err = snd_ctl_add(card, snd_ac97_cnew(ac97->spec.dev_flags ?  
                                                            &snd_ac97_control_alc650_mic :  
                                                            &snd_ac97_control_alc650_mic_gpio, ac97))) < 0)  
                         return err;  
                 if (ac97->ext_id & AC97_EI_SPDIF) {  
                         for (idx = 0; idx < ARRAY_SIZE(snd_ac97_spdif_controls_alc650); idx++)  
                                 if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_spdif_controls_alc650[idx], ac97))) < 0)  
                                         return err;  
                 }  
                 break;  
         case AC97_ID_VT1616:  
                 if (snd_ac97_try_bit(ac97, 0x5a, 9))  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_vt1616[0], ac97))) < 0)  
                                 return err;  
                 for (idx = 1; idx < ARRAY_SIZE(snd_ac97_controls_vt1616); idx++)  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_vt1616[idx], ac97))) < 0)  
                                 return err;  
                 break;  
         case AC97_ID_CM9739:  
                 for (idx = 1; idx < ARRAY_SIZE(snd_ac97_cm9739_controls); idx++)  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cm9739_controls[idx], ac97))) < 0)  
                                 return err;  
                 break;  
         case AC97_ID_CM9738:  
                 for (idx = 1; idx < ARRAY_SIZE(snd_ac97_cm9738_controls); idx++)  
                         if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_cm9738_controls[idx], ac97))) < 0)  
                                 return err;  
                 break;  
         default:  
                 /* nothing */  
                 break;  
         }  
1438    
1439          if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) {          if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) {
1440                  if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_eapd, ac97))) < 0)                  if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_eapd, ac97))) < 0)
# Line 1931  static int snd_ac97_test_rate(ac97_t *ac Line 1456  static int snd_ac97_test_rate(ac97_t *ac
1456          unsigned int tmp;          unsigned int tmp;
1457    
1458          tmp = ((unsigned int)rate * ac97->clock) / 48000;          tmp = ((unsigned int)rate * ac97->clock) / 48000;
1459          snd_ac97_write_cache_test(ac97, reg, tmp & 0xffff);          snd_ac97_write_cache(ac97, reg, tmp & 0xffff);
1460          val = snd_ac97_read(ac97, reg);          val = snd_ac97_read(ac97, reg);
1461          return val == (tmp & 0xffff);          return val == (tmp & 0xffff);
1462  }  }
# Line 1961  static void snd_ac97_determine_rates(ac9 Line 1486  static void snd_ac97_determine_rates(ac9
1486          *r_result = result;          *r_result = result;
1487  }  }
1488    
1489  static void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)  void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
1490  {  {
1491          const ac97_codec_id_t *pid;          const ac97_codec_id_t *pid;
1492    
# Line 2081  int snd_ac97_mixer(snd_card_t * card, ac Line 1606  int snd_ac97_mixer(snd_card_t * card, ac
1606          ac97->card = card;          ac97->card = card;
1607          spin_lock_init(&ac97->reg_lock);          spin_lock_init(&ac97->reg_lock);
1608    
1609            if (ac97->pci) {
1610                    pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor);
1611                    pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_ID, &ac97->subsystem_device);
1612            }
1613          if (ac97->reset) {          if (ac97->reset) {
1614                  ac97->reset(ac97);                  ac97->reset(ac97);
1615                  goto __access_ok;                  goto __access_ok;
# Line 2134  int snd_ac97_mixer(snd_card_t * card, ac Line 1663  int snd_ac97_mixer(snd_card_t * card, ac
1663          /* FIXME: add powerdown control */          /* FIXME: add powerdown control */
1664          if (ac97_is_audio(ac97)) {          if (ac97_is_audio(ac97)) {
1665                  /* nothing should be in powerdown mode */                  /* nothing should be in powerdown mode */
1666                  snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);                  snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
1667                  snd_ac97_write_cache_test(ac97, AC97_RESET, 0);         /* reset to defaults */                  snd_ac97_write_cache(ac97, AC97_RESET, 0);              /* reset to defaults */
1668                  udelay(100);                  udelay(100);
1669                  /* nothing should be in powerdown mode */                  /* nothing should be in powerdown mode */
1670                  snd_ac97_write_cache_test(ac97, AC97_POWERDOWN, 0);                  snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
1671                  snd_ac97_write_cache_test(ac97, AC97_GENERAL_PURPOSE, 0);                  snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
1672                  end_time = jiffies + (HZ / 10);                  end_time = jiffies + (HZ / 10);
1673                  do {                  do {
1674                          if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)                          if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
# Line 2208  int snd_ac97_mixer(snd_card_t * card, ac Line 1737  int snd_ac97_mixer(snd_card_t * card, ac
1737                          snd_ac97_free(ac97);                          snd_ac97_free(ac97);
1738                          return err;                          return err;
1739                  }                  }
1740          }                  if (snd_ac97_mixer_build(ac97) < 0) {
1741          if (ac97_is_audio(ac97) && snd_ac97_mixer_build(card, ac97) < 0) {                          snd_ac97_free(ac97);
1742                  snd_ac97_free(ac97);                          return -ENOMEM;
1743                  return -ENOMEM;                  }
1744          }          }
1745          snd_ac97_proc_init(card, ac97, "ac97");          snd_ac97_proc_init(card, ac97, "ac97");
1746          if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ac97, &ops)) < 0) {          if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ac97, &ops)) < 0) {
# Line 2353  int snd_ac97_modem(snd_card_t * card, ac Line 1882  int snd_ac97_modem(snd_card_t * card, ac
1882                  /* note: it's important to set the rate at first */                  /* note: it's important to set the rate at first */
1883                  tmp = AC97_MEA_GPIO;                  tmp = AC97_MEA_GPIO;
1884                  if (ac97->ext_mid & AC97_MEI_LINE1) {                  if (ac97->ext_mid & AC97_MEI_LINE1) {
1885                          snd_ac97_write_cache_test(ac97, AC97_LINE1_RATE, 12000);                          snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000);
1886                          tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;                          tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
1887                  }                  }
1888                  if (ac97->ext_mid & AC97_MEI_LINE2) {                  if (ac97->ext_mid & AC97_MEI_LINE2) {
1889                          snd_ac97_write_cache_test(ac97, AC97_LINE2_RATE, 12000);                          snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000);
1890                          tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;                          tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
1891                  }                  }
1892                  if (ac97->ext_mid & AC97_MEI_HANDSET) {                  if (ac97->ext_mid & AC97_MEI_HANDSET) {
1893                          snd_ac97_write_cache_test(ac97, AC97_HANDSET_RATE, 12000);                          snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000);
1894                          tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;                          tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
1895                  }                  }
1896                  snd_ac97_write_cache_test(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));                  snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
1897                  udelay(100);                  udelay(100);
1898                  /* nothing should be in powerdown mode */                  /* nothing should be in powerdown mode */
1899                  snd_ac97_write_cache_test(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));                  snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
1900                  end_time = jiffies + (HZ / 10);                  end_time = jiffies + (HZ / 10);
1901                  do {                  do {
1902                          if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)                          if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
# Line 2418  int snd_ac97_modem(snd_card_t * card, ac Line 1947  int snd_ac97_modem(snd_card_t * card, ac
1947  }  }
1948    
1949  /*  /*
  * proc interface  
  */  
   
 static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)  
 {  
         char name[64];  
         unsigned int id;  
         unsigned short val, tmp, ext, mext;  
         static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=res" };  
         static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" };  
         static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };  
   
         id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;  
         id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);  
         snd_ac97_get_name(NULL, id, name, 0);  
         snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);  
         if ((ac97->scaps & AC97_SCAP_AUDIO) == 0)  
                 goto __modem;  
   
         // val = snd_ac97_read(ac97, AC97_RESET);  
         val = ac97->caps;  
         snd_iprintf(buffer, "Capabilities     :%s%s%s%s%s%s\n",  
                     val & AC97_BC_DEDICATED_MIC ? " -dedicated MIC PCM IN channel-" : "",  
                     val & AC97_BC_RESERVED1 ? " -reserved1-" : "",  
                     val & AC97_BC_BASS_TREBLE ? " -bass & treble-" : "",  
                     val & AC97_BC_SIM_STEREO ? " -simulated stereo-" : "",  
                     val & AC97_BC_HEADPHONE ? " -headphone out-" : "",  
                     val & AC97_BC_LOUDNESS ? " -loudness-" : "");  
         tmp = ac97->caps & AC97_BC_DAC_MASK;  
         snd_iprintf(buffer, "DAC resolution   : %s%s%s%s\n",  
                     tmp == AC97_BC_16BIT_DAC ? "16-bit" : "",  
                     tmp == AC97_BC_18BIT_DAC ? "18-bit" : "",  
                     tmp == AC97_BC_20BIT_DAC ? "20-bit" : "",  
                     tmp == AC97_BC_DAC_MASK ? "???" : "");  
         tmp = ac97->caps & AC97_BC_ADC_MASK;  
         snd_iprintf(buffer, "ADC resolution   : %s%s%s%s\n",  
                     tmp == AC97_BC_16BIT_ADC ? "16-bit" : "",  
                     tmp == AC97_BC_18BIT_ADC ? "18-bit" : "",  
                     tmp == AC97_BC_20BIT_ADC ? "20-bit" : "",  
                     tmp == AC97_BC_ADC_MASK ? "???" : "");  
         snd_iprintf(buffer, "3D enhancement   : %s\n",  
                 snd_ac97_stereo_enhancements[(val >> 10) & 0x1f]);  
         snd_iprintf(buffer, "\nCurrent setup\n");  
         val = snd_ac97_read(ac97, AC97_MIC);  
         snd_iprintf(buffer, "Mic gain         : %s [%s]\n", val & 0x0040 ? "+20dB" : "+0dB", ac97->regs[AC97_MIC] & 0x0040 ? "+20dB" : "+0dB");  
         val = snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);  
         snd_iprintf(buffer, "POP path         : %s 3D\n"  
                     "Sim. stereo      : %s\n"  
                     "3D enhancement   : %s\n"  
                     "Loudness         : %s\n"  
                     "Mono output      : %s\n"  
                     "Mic select       : %s\n"  
                     "ADC/DAC loopback : %s\n",  
                     val & 0x8000 ? "post" : "pre",  
                     val & 0x4000 ? "on" : "off",  
                     val & 0x2000 ? "on" : "off",  
                     val & 0x1000 ? "on" : "off",  
                     val & 0x0200 ? "Mic" : "MIX",  
                     val & 0x0100 ? "Mic2" : "Mic1",  
                     val & 0x0080 ? "on" : "off");  
   
         ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);  
         if (ext == 0)  
                 goto __modem;  
                   
         snd_iprintf(buffer, "Extended ID      : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n",  
                         (ext & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT,  
                         (ext & AC97_EI_REV_MASK) >> AC97_EI_REV_SHIFT,  
                         ext & AC97_EI_AMAP ? " AMAP" : "",  
                         ext & AC97_EI_LDAC ? " LDAC" : "",  
                         ext & AC97_EI_SDAC ? " SDAC" : "",  
                         ext & AC97_EI_CDAC ? " CDAC" : "",  
                         (ext & AC97_EI_DACS_SLOT_MASK) >> AC97_EI_DACS_SLOT_SHIFT,  
                         ext & AC97_EI_VRM ? " VRM" : "",  
                         ext & AC97_EI_SPDIF ? " SPDIF" : "",  
                         ext & AC97_EI_DRA ? " DRA" : "",  
                         ext & AC97_EI_VRA ? " VRA" : "");  
         val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);  
         snd_iprintf(buffer, "Extended status  :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",  
                         val & AC97_EA_PRL ? " PRL" : "",  
                         val & AC97_EA_PRK ? " PRK" : "",  
                         val & AC97_EA_PRJ ? " PRJ" : "",  
                         val & AC97_EA_PRI ? " PRI" : "",  
                         val & AC97_EA_SPCV ? " SPCV" : "",  
                         val & AC97_EA_MDAC ? " MADC" : "",  
                         val & AC97_EA_LDAC ? " LDAC" : "",  
                         val & AC97_EA_SDAC ? " SDAC" : "",  
                         val & AC97_EA_CDAC ? " CDAC" : "",  
                         ext & AC97_EI_SPDIF ? spdif_slots[(val & AC97_EA_SPSA_SLOT_MASK) >> AC97_EA_SPSA_SLOT_SHIFT] : "",  
                         val & AC97_EA_VRM ? " VRM" : "",  
                         val & AC97_EA_SPDIF ? " SPDIF" : "",  
                         val & AC97_EA_DRA ? " DRA" : "",  
                         val & AC97_EA_VRA ? " VRA" : "");  
         if (ext & AC97_EI_VRA) {        /* VRA */  
                 val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE);  
                 snd_iprintf(buffer, "PCM front DAC    : %iHz\n", val);  
                 if (ext & AC97_EI_SDAC) {  
                         val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE);  
                         snd_iprintf(buffer, "PCM Surr DAC     : %iHz\n", val);  
                 }  
                 if (ext & AC97_EI_LDAC) {  
                         val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE);  
                         snd_iprintf(buffer, "PCM LFE DAC      : %iHz\n", val);  
                 }  
                 val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE);  
                 snd_iprintf(buffer, "PCM ADC          : %iHz\n", val);  
         }  
         if (ext & AC97_EI_VRM) {  
                 val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE);  
                 snd_iprintf(buffer, "PCM MIC ADC      : %iHz\n", val);  
         }  
         if ((ext & AC97_EI_SPDIF) || (ac97->flags & AC97_CS_SPDIF)) {  
                 if (ac97->flags & AC97_CS_SPDIF)  
                         val = snd_ac97_read(ac97, AC97_CSR_SPDIF);  
                 else  
                         val = snd_ac97_read(ac97, AC97_SPDIF);  
   
                 snd_iprintf(buffer, "SPDIF Control    :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n",  
                         val & AC97_SC_PRO ? " PRO" : " Consumer",  
                         val & AC97_SC_NAUDIO ? " Non-audio" : " PCM",  
                         val & AC97_SC_COPY ? " Copyright" : "",  
                         val & AC97_SC_PRE ? " Preemph50/15" : "",  
                         (val & AC97_SC_CC_MASK) >> AC97_SC_CC_SHIFT,  
                         (val & AC97_SC_L) >> 11,  
                         (ac97->flags & AC97_CS_SPDIF) ?  
                             spdif_rates_cs4205[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT] :  
                             spdif_rates[(val & AC97_SC_SPSR_MASK) >> AC97_SC_SPSR_SHIFT],  
                         (ac97->flags & AC97_CS_SPDIF) ?  
                             (val & AC97_SC_DRS ? " Validity" : "") :  
                             (val & AC97_SC_DRS ? " DRS" : ""),  
                         (ac97->flags & AC97_CS_SPDIF) ?  
                             (val & AC97_SC_V ? " Enabled" : "") :  
                             (val & AC97_SC_V ? " Validity" : ""));  
         }  
   
       __modem:  
         mext = snd_ac97_read(ac97, AC97_EXTENDED_MID);  
         if (mext == 0)  
                 return;  
           
         snd_iprintf(buffer, "Extended modem ID: codec=%i%s%s%s%s%s\n",  
                         (mext & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT,  
                         mext & AC97_MEI_CID2 ? " CID2" : "",  
                         mext & AC97_MEI_CID1 ? " CID1" : "",  
                         mext & AC97_MEI_HANDSET ? " HSET" : "",  
                         mext & AC97_MEI_LINE2 ? " LIN2" : "",  
                         mext & AC97_MEI_LINE1 ? " LIN1" : "");  
         val = snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS);  
         snd_iprintf(buffer, "Modem status     :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",  
                         val & AC97_MEA_GPIO ? " GPIO" : "",  
                         val & AC97_MEA_MREF ? " MREF" : "",  
                         val & AC97_MEA_ADC1 ? " ADC1" : "",  
                         val & AC97_MEA_DAC1 ? " DAC1" : "",  
                         val & AC97_MEA_ADC2 ? " ADC2" : "",  
                         val & AC97_MEA_DAC2 ? " DAC2" : "",  
                         val & AC97_MEA_HADC ? " HADC" : "",  
                         val & AC97_MEA_HDAC ? " HDAC" : "",  
                         val & AC97_MEA_PRA ? " PRA(GPIO)" : "",  
                         val & AC97_MEA_PRB ? " PRB(res)" : "",  
                         val & AC97_MEA_PRC ? " PRC(ADC1)" : "",  
                         val & AC97_MEA_PRD ? " PRD(DAC1)" : "",  
                         val & AC97_MEA_PRE ? " PRE(ADC2)" : "",  
                         val & AC97_MEA_PRF ? " PRF(DAC2)" : "",  
                         val & AC97_MEA_PRG ? " PRG(HADC)" : "",  
                         val & AC97_MEA_PRH ? " PRH(HDAC)" : "");  
         if (mext & AC97_MEI_LINE1) {  
                 val = snd_ac97_read(ac97, AC97_LINE1_RATE);  
                 snd_iprintf(buffer, "Line1 rate       : %iHz\n", val);  
         }  
         if (mext & AC97_MEI_LINE2) {  
                 val = snd_ac97_read(ac97, AC97_LINE2_RATE);  
                 snd_iprintf(buffer, "Line2 rate       : %iHz\n", val);  
         }  
         if (mext & AC97_MEI_HANDSET) {  
                 val = snd_ac97_read(ac97, AC97_HANDSET_RATE);  
                 snd_iprintf(buffer, "Headset rate     : %iHz\n", val);  
         }  
 }  
   
 static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)  
 {  
         ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);  
           
         if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {        // Analog Devices AD1881/85/86  
                 int idx;  
                 down(&ac97->spec.ad18xx.mutex);  
                 for (idx = 0; idx < 3; idx++)  
                         if (ac97->spec.ad18xx.id[idx]) {  
                                 /* select single codec */  
                                 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);  
                                 snd_ac97_proc_read_main(ac97, buffer, idx);  
                                 snd_iprintf(buffer, "\n\n");  
                         }  
                 /* select all codecs */  
                 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);  
                 up(&ac97->spec.ad18xx.mutex);  
                   
                 snd_iprintf(buffer, "\nAD18XX configuration\n");  
                 snd_iprintf(buffer, "Unchained        : 0x%04x,0x%04x,0x%04x\n",  
                         ac97->spec.ad18xx.unchained[0],  
                         ac97->spec.ad18xx.unchained[1],  
                         ac97->spec.ad18xx.unchained[2]);  
                 snd_iprintf(buffer, "Chained          : 0x%04x,0x%04x,0x%04x\n",  
                         ac97->spec.ad18xx.chained[0],  
                         ac97->spec.ad18xx.chained[1],  
                         ac97->spec.ad18xx.chained[2]);  
         } else {  
                 snd_ac97_proc_read_main(ac97, buffer, 0);  
         }  
 }  
   
 static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)  
 {  
         int reg, val;  
   
         for (reg = 0; reg < 0x80; reg += 2) {  
                 val = snd_ac97_read(ac97, reg);  
                 snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val);  
         }  
 }  
   
 static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,  
                                     snd_info_buffer_t * buffer)  
 {  
         ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);  
   
         if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {        // Analog Devices AD1881/85/86  
   
                 int idx;  
                 down(&ac97->spec.ad18xx.mutex);  
                 for (idx = 0; idx < 3; idx++)  
                         if (ac97->spec.ad18xx.id[idx]) {  
                                 /* select single codec */  
                                 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);  
                                 snd_ac97_proc_regs_read_main(ac97, buffer, idx);  
                         }  
                 /* select all codecs */  
                 snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000);  
                 up(&ac97->spec.ad18xx.mutex);  
         } else {  
                 snd_ac97_proc_regs_read_main(ac97, buffer, 0);  
         }        
 }  
   
 static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97, const char *prefix)  
 {  
         snd_info_entry_t *entry;  
         char name[32];  
   
         if (ac97->num)  
                 sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);  
         else  
                 sprintf(name, "%s#%d", prefix, ac97->addr);  
         if (! snd_card_proc_new(card, name, &entry))  
                 snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);  
         if (ac97->num)  
                 sprintf(name, "%s#%d-%dregs", prefix, ac97->addr, ac97->num);  
         else  
                 sprintf(name, "%s#%dregs", prefix, ac97->addr);  
         if (! snd_card_proc_new(card, name, &entry))  
                 snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);  
 }  
   
 /*  
1950   *  PCM support   *  PCM support
1951   */   */
1952    
# Line 2720  static int set_spdif_rate(ac97_t *ac97, Line 1985  static int set_spdif_rate(ac97_t *ac97,
1985          }          }
1986    
1987          spin_lock(&ac97->reg_lock);          spin_lock(&ac97->reg_lock);
1988          old = ac97->regs[reg] & ~mask;          old = ac97->regs[reg] & mask;
1989          spin_unlock(&ac97->reg_lock);          spin_unlock(&ac97->reg_lock);
1990          if (old != bits) {          if (old != bits) {
1991                  snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);                  snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26