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

Diff of /alsa/alsa-kernel/pci/ac97/ac97_patch.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 3  Line 3 
3   *  Universal interface for Audio Codec '97   *  Universal interface for Audio Codec '97
4   *   *
5   *  For more details look to AC '97 component specification revision 2.2   *  For more details look to AC '97 component specification revision 2.2
6   *  by Intel Corporation (http://developer.intel.com).   *  by Intel Corporation (http://developer.intel.com) and to datasheets
7     *  for specific codecs.
8   *   *
9   *   *
10   *   This program is free software; you can redistribute it and/or modify   *   This program is free software; you can redistribute it and/or modify
# Line 28  Line 29 
29  #include <linux/slab.h>  #include <linux/slab.h>
30  #include <sound/core.h>  #include <sound/core.h>
31  #include <sound/pcm.h>  #include <sound/pcm.h>
32    #include <sound/control.h>
33  #include <sound/ac97_codec.h>  #include <sound/ac97_codec.h>
 #include <sound/asoundef.h>  
 #include <sound/initval.h>  
34  #include "ac97_patch.h"  #include "ac97_patch.h"
35    #include "ac97_id.h"
36    #include "ac97_local.h"
37    
38    #define chip_t ac97_t
39    
40  /*  /*
41   *  Chip specific initialization   *  Chip specific initialization
42   */   */
43    
44    static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *controls, int count)
45    {
46            int idx, err;
47    
48            for (idx = 0; idx < count; idx++)
49                    if ((err = snd_ctl_add(ac97->card, snd_ac97_cnew(&controls[idx], ac97))) < 0)
50                            return err;
51            return 0;
52    }
53    
54    /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
55    
56    /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
57    static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
58    {
59            static char *texts[3] = {
60                    "Standard", "Small", "Smaller"
61            };
62    
63            uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
64            uinfo->count = 1;
65            uinfo->value.enumerated.items = 3;
66            if (uinfo->value.enumerated.item > 2)
67                    uinfo->value.enumerated.item = 2;
68            strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
69            return 0;
70    }
71    
72    static int snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
73    {
74            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
75            unsigned short val;
76    
77            val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
78            val = (val >> 10) & 3;
79            if (val > 0)    /* 0 = invalid */
80                    val--;
81            ucontrol->value.enumerated.item[0] = val;
82            return 0;
83    }
84    
85    static int snd_ac97_ymf753_put_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
86    {
87            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
88            unsigned short val;
89    
90            if (ucontrol->value.enumerated.item[0] > 2)
91                    return -EINVAL;
92            val = (ucontrol->value.enumerated.item[0] + 1) << 10;
93            return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
94    }
95    
96    static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
97    {
98            .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
99            .name   = "3D Control - Speaker",
100            .info   = snd_ac97_ymf753_info_speaker,
101            .get    = snd_ac97_ymf753_get_speaker,
102            .put    = snd_ac97_ymf753_put_speaker,
103    };
104    
105    /* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */
106    static int snd_ac97_ymf753_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
107    {
108            static char *texts[2] = { "AC-Link", "A/D Converter" };
109    
110            uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
111            uinfo->count = 1;
112            uinfo->value.enumerated.items = 2;
113            if (uinfo->value.enumerated.item > 1)
114                    uinfo->value.enumerated.item = 1;
115            strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
116            return 0;
117    }
118    
119    static int snd_ac97_ymf753_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
120    {
121            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
122            unsigned short val;
123    
124            val = ac97->regs[AC97_YMF753_DIT_CTRL2];
125            ucontrol->value.enumerated.item[0] = (val >> 1) & 1;
126            return 0;
127    }
128    
129    static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
130    {
131            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
132            unsigned short val;
133    
134            if (ucontrol->value.enumerated.item[0] > 1)
135                    return -EINVAL;
136            val = ucontrol->value.enumerated.item[0] << 1;
137            return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0002, val);
138    }
139    
140    /* The AC'97 spec states that the S/PDIF signal is to be output at pin 48.
141       The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
142       By default, no output pin is selected, and the S/PDIF signal is not output.
143       There is also a bit to mute S/PDIF output in a vendor-specific register. */
144    static int snd_ac97_ymf753_spdif_output_pin_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
145    {
146            static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
147    
148            uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
149            uinfo->count = 1;
150            uinfo->value.enumerated.items = 3;
151            if (uinfo->value.enumerated.item > 2)
152                    uinfo->value.enumerated.item = 2;
153            strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
154            return 0;
155    }
156    
157    static int snd_ac97_ymf753_spdif_output_pin_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
158    {
159            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
160            unsigned short val;
161    
162            val = ac97->regs[AC97_YMF753_DIT_CTRL2];
163            ucontrol->value.enumerated.item[0] = (val & 0x0008) ? 2 : (val & 0x0020) ? 1 : 0;
164            return 0;
165    }
166    
167    static int snd_ac97_ymf753_spdif_output_pin_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
168    {
169            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
170            unsigned short val;
171    
172            if (ucontrol->value.enumerated.item[0] > 2)
173                    return -EINVAL;
174            val = (ucontrol->value.enumerated.item[0] == 2) ? 0x0008 :
175                  (ucontrol->value.enumerated.item[0] == 1) ? 0x0020 : 0;
176            return snd_ac97_update_bits(ac97, AC97_YMF753_DIT_CTRL2, 0x0028, val);
177            /* The following can be used to direct S/PDIF output to pin 47 (EAPD).
178               snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
179    }
180    
181    static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
182            {
183                    .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
184                    .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
185                    .info   = snd_ac97_ymf753_spdif_source_info,
186                    .get    = snd_ac97_ymf753_spdif_source_get,
187                    .put    = snd_ac97_ymf753_spdif_source_put,
188            },
189            {
190                    .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
191                    .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Output Pin",
192                    .info   = snd_ac97_ymf753_spdif_output_pin_info,
193                    .get    = snd_ac97_ymf753_spdif_output_pin_get,
194                    .put    = snd_ac97_ymf753_spdif_output_pin_put,
195            },
196            AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1)
197    };
198    
199    static int patch_yamaha_ymf753_3d(ac97_t * ac97)
200    {
201            snd_kcontrol_t *kctl;
202            int err;
203    
204            if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
205                    return err;
206            strcpy(kctl->id.name, "3D Control - Wide");
207            kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
208            snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
209            if ((err = snd_ctl_add(ac97->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
210                    return err;
211            snd_ac97_write_cache(ac97, AC97_YMF753_3D_MODE_SEL, 0x0c00);
212            return 0;
213    }
214    
215    static int patch_yamaha_ymf753_post_spdif(ac97_t * ac97)
216    {
217            int err;
218    
219            if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0)
220                    return err;
221            return 0;
222    }
223    
224    static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
225            .build_3d       = patch_yamaha_ymf753_3d,
226            .build_post_spdif = patch_yamaha_ymf753_post_spdif
227    };
228    
229  int patch_yamaha_ymf753(ac97_t * ac97)  int patch_yamaha_ymf753(ac97_t * ac97)
230  {  {
231          /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.          /* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
# Line 46  int patch_yamaha_ymf753(ac97_t * ac97) Line 235  int patch_yamaha_ymf753(ac97_t * ac97)
235             By default, no output pin is selected, and the S/PDIF signal is not output.             By default, no output pin is selected, and the S/PDIF signal is not output.
236             There is also a bit to mute S/PDIF output in a vendor-specific register.             There is also a bit to mute S/PDIF output in a vendor-specific register.
237          */          */
238            ac97->build_ops = &patch_yamaha_ymf753_ops;
239          ac97->caps |= AC97_BC_BASS_TREBLE;          ac97->caps |= AC97_BC_BASS_TREBLE;
240          ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */          ac97->caps |= 0x04 << 10; /* Yamaha 3D enhancement */
241          return 0;          return 0;
# Line 57  int patch_yamaha_ymf753(ac97_t * ac97) Line 247  int patch_yamaha_ymf753(ac97_t * ac97)
247   *  added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.   *  added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
248   */   */
249    
 #define AC97_WM97XX_FMIXER_VOL  0x72  
 #define AC97_WM9704_RMIXER_VOL  0x74  
 #define AC97_WM9704_TEST        0x5a  
 #define AC97_WM9704_RPCM_VOL    0x70  
 #define AC97_WM9711_OUT3VOL     0x16  
   
250  int patch_wolfson03(ac97_t * ac97)  int patch_wolfson03(ac97_t * ac97)
251  {  {
252          /* This is known to work for the ViewSonic ViewPad 1000          /* This is known to work for the ViewSonic ViewPad 1000
# Line 117  int patch_tritech_tr28028(ac97_t * ac97) Line 301  int patch_tritech_tr28028(ac97_t * ac97)
301          return 0;          return 0;
302  }  }
303    
304    static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
305    {
306            snd_kcontrol_t *kctl;
307            int err;
308    
309            if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
310                    return err;
311            strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
312            kctl->private_value = AC97_3D_CONTROL | (3 << 16);
313            snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
314            return 0;
315    }
316    
317    static int patch_sigmatel_stac9708_3d(ac97_t * ac97)
318    {
319            snd_kcontrol_t *kctl;
320            int err;
321    
322            if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
323                    return err;
324            strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
325            kctl->private_value = AC97_3D_CONTROL | (3 << 16);
326            if ((err = snd_ctl_add(ac97->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
327                    return err;
328            strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
329            kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);
330            snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
331            return 0;
332    }
333    
334    static const snd_kcontrol_new_t snd_ac97_sigmatel_4speaker =
335    AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
336    
337    static const snd_kcontrol_new_t snd_ac97_sigmatel_phaseinvert =
338    AC97_SINGLE("Sigmatel Surround Phase Inversion Playback Switch", AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
339    
340    static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {
341    AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
342    AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
343    };
344    
345    static int patch_sigmatel_stac97xx_specific(ac97_t * ac97)
346    {
347            int err;
348    
349            snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003);
350            if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1))
351                    if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0)
352                            return err;
353            if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0))
354                    if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0)
355                            return err;
356            if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2))
357                    if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0)
358                            return err;
359            if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3))
360                    if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0)
361                            return err;
362            return 0;
363    }
364    
365    static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
366            .build_3d       = patch_sigmatel_stac9700_3d,
367            .build_specific = patch_sigmatel_stac97xx_specific
368    };
369    
370    static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
371            .build_3d       = patch_sigmatel_stac9708_3d,
372            .build_specific = patch_sigmatel_stac97xx_specific
373    };
374    
375    int patch_sigmatel_stac9700(ac97_t * ac97)
376    {
377            ac97->build_ops = &patch_sigmatel_stac9700_ops;
378            return 0;
379    }
380    
381  int patch_sigmatel_stac9708(ac97_t * ac97)  int patch_sigmatel_stac9708(ac97_t * ac97)
382  {  {
383          unsigned int codec72, codec6c;          unsigned int codec72, codec6c;
384    
385            ac97->build_ops = &patch_sigmatel_stac9708_ops;
386    
387          codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;          codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
388          codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);          codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
389    
# Line 142  int patch_sigmatel_stac9708(ac97_t * ac9 Line 405  int patch_sigmatel_stac9708(ac97_t * ac9
405    
406  int patch_sigmatel_stac9721(ac97_t * ac97)  int patch_sigmatel_stac9721(ac97_t * ac97)
407  {  {
408            ac97->build_ops = &patch_sigmatel_stac9700_ops;
409          if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {          if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
410                  // patch for SigmaTel                  // patch for SigmaTel
411                  snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);                  snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
# Line 156  int patch_sigmatel_stac9721(ac97_t * ac9 Line 420  int patch_sigmatel_stac9721(ac97_t * ac9
420  int patch_sigmatel_stac9744(ac97_t * ac97)  int patch_sigmatel_stac9744(ac97_t * ac97)
421  {  {
422          // patch for SigmaTel          // patch for SigmaTel
423            ac97->build_ops = &patch_sigmatel_stac9700_ops;
424          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
425          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
426          snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);          snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
# Line 167  int patch_sigmatel_stac9744(ac97_t * ac9 Line 432  int patch_sigmatel_stac9744(ac97_t * ac9
432  int patch_sigmatel_stac9756(ac97_t * ac97)  int patch_sigmatel_stac9756(ac97_t * ac97)
433  {  {
434          // patch for SigmaTel          // patch for SigmaTel
435            ac97->build_ops = &patch_sigmatel_stac9700_ops;
436          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba);
437          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */          snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */
438          snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);          snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
# Line 175  int patch_sigmatel_stac9756(ac97_t * ac9 Line 441  int patch_sigmatel_stac9756(ac97_t * ac9
441          return 0;          return 0;
442  }  }
443    
444    static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
445            AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
446            AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
447    };
448    
449    static int patch_cirrus_build_spdif(ac97_t * ac97)
450    {
451            int err;
452    
453            if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
454                    return err;
455            if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
456                    return err;
457            switch (ac97->id & AC97_ID_CS_MASK) {
458            case AC97_ID_CS4205:
459                    if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1)) < 0)
460                            return err;
461                    break;
462            }
463            /* set default PCM S/PDIF params */
464            /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
465            snd_ac97_write_cache(ac97, AC97_CSR_SPDIF, 0x0a20);
466            return 0;
467    }
468    
469    static struct snd_ac97_build_ops patch_cirrus_ops = {
470            .build_spdif = patch_cirrus_build_spdif
471    };
472    
473  int patch_cirrus_spdif(ac97_t * ac97)  int patch_cirrus_spdif(ac97_t * ac97)
474  {  {
475          /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.          /* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
# Line 188  int patch_cirrus_spdif(ac97_t * ac97) Line 483  int patch_cirrus_spdif(ac97_t * ac97)
483             - sp/dif ssource select is in 0x5e bits 0,1.             - sp/dif ssource select is in 0x5e bits 0,1.
484          */          */
485    
486            ac97->build_ops = &patch_cirrus_ops;
487          ac97->flags |= AC97_CS_SPDIF;          ac97->flags |= AC97_CS_SPDIF;
488          ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;          ac97->rates[AC97_RATES_SPDIF] &= ~SNDRV_PCM_RATE_32000;
489          ac97->ext_id |= AC97_EI_SPDIF;  /* force the detection of spdif */          ac97->ext_id |= AC97_EI_SPDIF;  /* force the detection of spdif */
# Line 203  int patch_cirrus_cs4299(ac97_t * ac97) Line 499  int patch_cirrus_cs4299(ac97_t * ac97)
499          return patch_cirrus_spdif(ac97);          return patch_cirrus_spdif(ac97);
500  }  }
501    
502    static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[1] = {
503            AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
504    };
505    
506    static int patch_conexant_build_spdif(ac97_t * ac97)
507    {
508            int err;
509    
510            if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
511                    return err;
512            if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
513                    return err;
514            /* set default PCM S/PDIF params */
515            /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
516            snd_ac97_write_cache(ac97, AC97_CXR_AUDIO_MISC,
517                                 snd_ac97_read(ac97, AC97_CXR_AUDIO_MISC) & ~(AC97_CXR_SPDIFEN|AC97_CXR_COPYRGT|AC97_CXR_SPDIF_MASK));
518            return 0;
519    }
520    
521    static struct snd_ac97_build_ops patch_conexant_ops = {
522            .build_spdif = patch_conexant_build_spdif
523    };
524    
525  int patch_conexant(ac97_t * ac97)  int patch_conexant(ac97_t * ac97)
526  {  {
527            ac97->build_ops = &patch_conexant_ops;
528          ac97->flags |= AC97_CX_SPDIF;          ac97->flags |= AC97_CX_SPDIF;
529          ac97->ext_id |= AC97_EI_SPDIF;  /* force the detection of spdif */          ac97->ext_id |= AC97_EI_SPDIF;  /* force the detection of spdif */
530          return 0;          return 0;
# Line 330  int patch_ad1881(ac97_t * ac97) Line 650  int patch_ad1881(ac97_t * ac97)
650          return 0;          return 0;
651  }  }
652    
653    static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
654            AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
655            AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0),
656            AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
657            AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
658    };
659    
660    static int patch_ad1885_specific(ac97_t * ac97)
661    {
662            int err;
663    
664            if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0)
665                    return err;
666            return 0;
667    }
668    
669    static struct snd_ac97_build_ops patch_ad1885_build_ops = {
670            .build_specific = &patch_ad1885_specific
671    };
672    
673  int patch_ad1885(ac97_t * ac97)  int patch_ad1885(ac97_t * ac97)
674  {  {
675          unsigned short jack;          unsigned short jack;
# Line 341  int patch_ad1885(ac97_t * ac97) Line 681  int patch_ad1885(ac97_t * ac97)
681          /* turn off jack sense bits D8 & D9 */          /* turn off jack sense bits D8 & D9 */
682          jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF);          jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF);
683          snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300);          snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300);
684    
685            ac97->build_ops = &patch_ad1885_build_ops;
686          return 0;          return 0;
687  }  }
688    
# Line 353  int patch_ad1886(ac97_t * ac97) Line 695  int patch_ad1886(ac97_t * ac97)
695          return 0;          return 0;
696  }  }
697    
698    static int snd_ac97_ad1980_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
699    {
700            static char *texts[2] = { "AC-Link", "A/D Converter" };
701    
702            uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
703            uinfo->count = 1;
704            uinfo->value.enumerated.items = 2;
705            if (uinfo->value.enumerated.item > 1)
706                    uinfo->value.enumerated.item = 1;
707            strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
708            return 0;
709    }
710    
711    static int snd_ac97_ad1980_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
712    {
713            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
714            unsigned short val;
715    
716            val = ac97->regs[AC97_AD_SERIAL_CFG];
717            ucontrol->value.enumerated.item[0] = (val >> 2) & 1;
718            return 0;
719    }
720    
721    static int snd_ac97_ad1980_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
722    {
723            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
724            unsigned short val;
725    
726            if (ucontrol->value.enumerated.item[0] > 1)
727                    return -EINVAL;
728            val = ucontrol->value.enumerated.item[0] << 2;
729            return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
730    }
731    
732    static const snd_kcontrol_new_t snd_ac97_ad1980_spdif_source = {
733            .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
734            .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
735            .info   = snd_ac97_ad1980_spdif_source_info,
736            .get    = snd_ac97_ad1980_spdif_source_get,
737            .put    = snd_ac97_ad1980_spdif_source_put,
738    };
739    
740    static int patch_ad1980_post_spdif(ac97_t * ac97)
741    {
742            return patch_build_controls(ac97, &snd_ac97_ad1980_spdif_source, 1);
743    }
744    
745    static struct snd_ac97_build_ops patch_ad1980_build_ops = {
746            .build_post_spdif = &patch_ad1980_post_spdif
747    };
748    
749  int patch_ad1980(ac97_t * ac97)  int patch_ad1980(ac97_t * ac97)
750  {  {
751          unsigned short misc;          unsigned short misc;
752                    
753          patch_ad1881(ac97);          patch_ad1881(ac97);
754            ac97->build_ops = &patch_ad1980_build_ops;
755          /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */          /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
756          /* it seems that most vendors connect line-out connector to headphone out of AC'97 */          /* it seems that most vendors connect line-out connector to headphone out of AC'97 */
757          misc = snd_ac97_read(ac97, AC97_AD_MISC);          misc = snd_ac97_read(ac97, AC97_AD_MISC);
# Line 365  int patch_ad1980(ac97_t * ac97) Line 759  int patch_ad1980(ac97_t * ac97)
759          return 0;          return 0;
760  }  }
761    
762    static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
763            AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
764            AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
765            AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
766            AC97_SINGLE("Exchange Center/LFE", AC97_ALC650_MULTICH, 3, 1, 0),
767            /* 4: Analog Input To Surround */
768            /* 5: Analog Input To Center/LFE */
769            /* 6: Independent Master Volume Right */
770            /* 7: Independent Master Volume Left */
771            /* 8: reserved */
772            AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
773            AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
774    #if 0 /* always set in patch_alc650 */
775            AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0),
776            AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0),
777            AC97_SINGLE("Surround DAC Switch", AC97_ALC650_SURR_DAC_VOL, 15, 1, 1),
778            AC97_DOUBLE("Surround DAC Volume", AC97_ALC650_SURR_DAC_VOL, 8, 0, 31, 1),
779            AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
780            AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
781    #endif
782    };
783    
784    static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =
785    AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);
786    
787    static int snd_ac97_alc650_mic_gpio_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
788    {
789            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
790            ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
791            return 0;
792    }
793    
794    static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
795    {
796            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
797            int change;
798            change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
799                                          ucontrol->value.integer.value[0] ? (1 << 10) : 0);
800            if (change) {
801                    /* GPIO0 write for mic */
802                    snd_ac97_update_bits(ac97, 0x76, 0x01,
803                                         ucontrol->value.integer.value[0] ? 0 : 0x01);
804                    /* GPIO0 high for mic */
805                    snd_ac97_update_bits(ac97, 0x78, 0x100,
806                                         ucontrol->value.integer.value[0] ? 0 : 0x100);
807            }
808            return change;
809    }
810    
811    static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {
812            .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
813            .name = "Mic As Center/LFE",
814            .info = snd_ac97_info_single,
815            .get = snd_ac97_alc650_mic_gpio_get,
816            .put = snd_ac97_alc650_mic_gpio_put,
817            .private_value = (1 << 16), /* for info */
818    };
819    
820    static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
821            AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
822            AC97_SINGLE("Analog to IEC958 Output", AC97_ALC650_MULTICH, 12, 1, 0),
823            AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0),
824    };
825    
826    static int patch_alc650_specific(ac97_t * ac97)
827    {
828            int err;
829    
830            if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
831                    return err;
832            if ((err = patch_build_controls(ac97,
833                                            ac97->spec.dev_flags ?
834                                                    &snd_ac97_control_alc650_mic :
835                                                    &snd_ac97_control_alc650_mic_gpio, 1)) < 0)
836                    return err;
837            if (ac97->ext_id & AC97_EI_SPDIF) {
838                    if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
839                            return err;
840            }
841            return 0;
842    }
843    
844    static struct snd_ac97_build_ops patch_alc650_ops = {
845            .build_specific = patch_alc650_specific
846    };
847    
848  int patch_alc650(ac97_t * ac97)  int patch_alc650(ac97_t * ac97)
849  {  {
850          unsigned short val;          unsigned short val;
851          int spdif = 0;          int spdif = 0;
852    
853          /* FIXME: set the above 1 if we can detect the chip rev.E correctly.          /* FIXME: set the below 1 if we can detect the chip rev.E correctly.
854           *        this is used for switching mic and center/lfe, which needs           *        this is used for switching mic and center/lfe, which needs
855           *        resetting GPIO0 level on the older revision.           *        resetting GPIO0 level on the older revision.
856           */           */
857            ac97->build_ops = &patch_alc650_ops;
858          ac97->spec.dev_flags = 0;          ac97->spec.dev_flags = 0;
859    
860          /* check spdif */          /* check spdif (should be only on rev.E) */
861          if (ac97->spec.dev_flags) {          val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
862                  val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);          if (val & AC97_EA_SPCV)
863                  if (val & AC97_EA_SPCV)                  spdif = 1;
864                          spdif = 1;  
         }  
865          if (spdif) {          if (spdif) {
866                  /* enable spdif in */                  /* enable spdif in */
867                  snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,                  snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
# Line 418  int patch_alc650(ac97_t * ac97) Line 898  int patch_alc650(ac97_t * ac97)
898          return 0;          return 0;
899  }  }
900    
901    static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
902            AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
903            AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
904    };
905    
906    static int patch_cm9738_specific(ac97_t * ac97)
907    {
908            return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
909    }
910    
911    static struct snd_ac97_build_ops patch_cm9738_ops = {
912            .build_specific = patch_cm9738_specific
913    };
914    
915    int patch_cm9738(ac97_t * ac97)
916    {
917            ac97->build_ops = &patch_cm9738_ops;
918            return 0;
919    }
920    
921    static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
922    {
923            static char *texts[] = { "Analog", "Digital" };
924    
925            uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
926            uinfo->count = 1;
927            uinfo->value.enumerated.items = 2;
928            if (uinfo->value.enumerated.item > 1)
929                    uinfo->value.enumerated.item = 1;
930            strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
931            return 0;
932    }
933    
934    static int snd_ac97_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
935    {
936            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
937            unsigned short val;
938    
939            val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
940            ucontrol->value.enumerated.item[0] = (val >> 1) & 0x01;
941            return 0;
942    }
943    
944    static int snd_ac97_cmedia_spdif_playback_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
945    {
946            ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
947    
948            return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
949                                        0x01 << 1,
950                                        (ucontrol->value.enumerated.item[0] & 0x01) << 1);
951    }
952    
953    static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
954            /* BIT 0: SPDI_EN - always true */
955            { /* BIT 1: SPDIFS */
956                    .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
957                    .name   = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
958                    .info   = snd_ac97_cmedia_spdif_playback_source_info,
959                    .get    = snd_ac97_cmedia_spdif_playback_source_get,
960                    .put    = snd_ac97_cmedia_spdif_playback_source_put,
961            },
962            /* BIT 2: IG_SPIV */
963            AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9739_SPDIF_CTRL, 2, 1, 0),
964            /* BIT 3: SPI2F */
965            AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9739_SPDIF_CTRL, 3, 1, 0),
966            /* BIT 4: SPI2SDI */
967            AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9739_SPDIF_CTRL, 4, 1, 0),
968            /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
969    };
970    
971    static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
972            AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
973    };
974    
975    static int patch_cm9739_specific(ac97_t * ac97)
976    {
977            return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
978    }
979    
980    static int patch_cm9739_post_spdif(ac97_t * ac97)
981    {
982            return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
983    }
984    
985    static struct snd_ac97_build_ops patch_cm9739_ops = {
986            .build_specific = patch_cm9739_specific,
987            .build_post_spdif = patch_cm9739_post_spdif
988    };
989    
990  int patch_cm9739(ac97_t * ac97)  int patch_cm9739(ac97_t * ac97)
991  {  {
992          unsigned short val;          unsigned short val;
993    
994            ac97->build_ops = &patch_cm9739_ops;
995    
996          /* check spdif */          /* check spdif */
997          val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);          val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
998          if (val & AC97_EA_SPCV) {          if (val & AC97_EA_SPCV) {
# Line 445  int patch_cm9739(ac97_t * ac97) Line 1016  int patch_cm9739(ac97_t * ac97)
1016          return 0;          return 0;
1017  }  }
1018    
1019    static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
1020    AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
1021    AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
1022    AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
1023    AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
1024    };
1025    
1026    static int patch_vt1616_specific(ac97_t * ac97)
1027    {
1028            int err;
1029    
1030            if (snd_ac97_try_bit(ac97, 0x5a, 9))
1031                    if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0)
1032                            return err;
1033            if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
1034                    return err;
1035            return 0;
1036    }
1037    
1038    static struct snd_ac97_build_ops patch_vt1616_ops = {
1039            .build_specific = patch_vt1616_specific
1040    };
1041    
1042    int patch_vt1616(ac97_t * ac97)
1043    {
1044            ac97->build_ops = &patch_vt1616_ops;
1045            return 0;
1046    }

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