~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/ice1712/maya44.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /sound/pci/ice1712/maya44.c (Version linux-6.12-rc7) and /sound/pci/ice1712/maya44.c (Version linux-6.5.13)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*                                                  2 /*
  3  *   ALSA driver for ICEnsemble VT1724 (Envy24      3  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
  4  *                                                  4  *
  5  *   Lowlevel functions for ESI Maya44 cards        5  *   Lowlevel functions for ESI Maya44 cards
  6  *                                                  6  *
  7  *      Copyright (c) 2009 Takashi Iwai <tiwai      7  *      Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
  8  *      Based on the patches by Rainer Zimmerm      8  *      Based on the patches by Rainer Zimmermann <mail@lightshed.de>
  9  */                                                 9  */
 10                                                    10 
 11 #include <linux/init.h>                            11 #include <linux/init.h>
 12 #include <linux/slab.h>                            12 #include <linux/slab.h>
 13 #include <sound/core.h>                            13 #include <sound/core.h>
 14 #include <sound/control.h>                         14 #include <sound/control.h>
 15 #include <sound/pcm.h>                             15 #include <sound/pcm.h>
 16 #include <sound/tlv.h>                             16 #include <sound/tlv.h>
 17                                                    17 
 18 #include "ice1712.h"                               18 #include "ice1712.h"
 19 #include "envy24ht.h"                              19 #include "envy24ht.h"
 20 #include "maya44.h"                                20 #include "maya44.h"
 21                                                    21 
 22 /* WM8776 register indexes */                      22 /* WM8776 register indexes */
 23 #define WM8776_REG_HEADPHONE_L          0x00       23 #define WM8776_REG_HEADPHONE_L          0x00
 24 #define WM8776_REG_HEADPHONE_R          0x01       24 #define WM8776_REG_HEADPHONE_R          0x01
 25 #define WM8776_REG_HEADPHONE_MASTER     0x02       25 #define WM8776_REG_HEADPHONE_MASTER     0x02
 26 #define WM8776_REG_DAC_ATTEN_L          0x03       26 #define WM8776_REG_DAC_ATTEN_L          0x03
 27 #define WM8776_REG_DAC_ATTEN_R          0x04       27 #define WM8776_REG_DAC_ATTEN_R          0x04
 28 #define WM8776_REG_DAC_ATTEN_MASTER     0x05       28 #define WM8776_REG_DAC_ATTEN_MASTER     0x05
 29 #define WM8776_REG_DAC_PHASE            0x06       29 #define WM8776_REG_DAC_PHASE            0x06
 30 #define WM8776_REG_DAC_CONTROL          0x07       30 #define WM8776_REG_DAC_CONTROL          0x07
 31 #define WM8776_REG_DAC_MUTE             0x08       31 #define WM8776_REG_DAC_MUTE             0x08
 32 #define WM8776_REG_DAC_DEEMPH           0x09       32 #define WM8776_REG_DAC_DEEMPH           0x09
 33 #define WM8776_REG_DAC_IF_CONTROL       0x0a       33 #define WM8776_REG_DAC_IF_CONTROL       0x0a
 34 #define WM8776_REG_ADC_IF_CONTROL       0x0b       34 #define WM8776_REG_ADC_IF_CONTROL       0x0b
 35 #define WM8776_REG_MASTER_MODE_CONTROL  0x0c       35 #define WM8776_REG_MASTER_MODE_CONTROL  0x0c
 36 #define WM8776_REG_POWERDOWN            0x0d       36 #define WM8776_REG_POWERDOWN            0x0d
 37 #define WM8776_REG_ADC_ATTEN_L          0x0e       37 #define WM8776_REG_ADC_ATTEN_L          0x0e
 38 #define WM8776_REG_ADC_ATTEN_R          0x0f       38 #define WM8776_REG_ADC_ATTEN_R          0x0f
 39 #define WM8776_REG_ADC_ALC1             0x10       39 #define WM8776_REG_ADC_ALC1             0x10
 40 #define WM8776_REG_ADC_ALC2             0x11       40 #define WM8776_REG_ADC_ALC2             0x11
 41 #define WM8776_REG_ADC_ALC3             0x12       41 #define WM8776_REG_ADC_ALC3             0x12
 42 #define WM8776_REG_ADC_NOISE_GATE       0x13       42 #define WM8776_REG_ADC_NOISE_GATE       0x13
 43 #define WM8776_REG_ADC_LIMITER          0x14       43 #define WM8776_REG_ADC_LIMITER          0x14
 44 #define WM8776_REG_ADC_MUX              0x15       44 #define WM8776_REG_ADC_MUX              0x15
 45 #define WM8776_REG_OUTPUT_MUX           0x16       45 #define WM8776_REG_OUTPUT_MUX           0x16
 46 #define WM8776_REG_RESET                0x17       46 #define WM8776_REG_RESET                0x17
 47                                                    47 
 48 #define WM8776_NUM_REGS                 0x18       48 #define WM8776_NUM_REGS                 0x18
 49                                                    49 
 50 /* clock ratio identifiers for snd_wm8776_set_     50 /* clock ratio identifiers for snd_wm8776_set_rate() */
 51 #define WM8776_CLOCK_RATIO_128FS        0          51 #define WM8776_CLOCK_RATIO_128FS        0
 52 #define WM8776_CLOCK_RATIO_192FS        1          52 #define WM8776_CLOCK_RATIO_192FS        1
 53 #define WM8776_CLOCK_RATIO_256FS        2          53 #define WM8776_CLOCK_RATIO_256FS        2
 54 #define WM8776_CLOCK_RATIO_384FS        3          54 #define WM8776_CLOCK_RATIO_384FS        3
 55 #define WM8776_CLOCK_RATIO_512FS        4          55 #define WM8776_CLOCK_RATIO_512FS        4
 56 #define WM8776_CLOCK_RATIO_768FS        5          56 #define WM8776_CLOCK_RATIO_768FS        5
 57                                                    57 
 58 enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_N     58 enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
 59 enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHE     59 enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
 60                                                    60 
 61 struct snd_wm8776 {                                61 struct snd_wm8776 {
 62         unsigned char addr;                        62         unsigned char addr;
 63         unsigned short regs[WM8776_NUM_REGS];      63         unsigned short regs[WM8776_NUM_REGS];
 64         unsigned char volumes[WM_NUM_VOLS][2];     64         unsigned char volumes[WM_NUM_VOLS][2];
 65         unsigned int switch_bits;                  65         unsigned int switch_bits;
 66 };                                                 66 };
 67                                                    67 
 68 struct snd_maya44 {                                68 struct snd_maya44 {
 69         struct snd_ice1712 *ice;                   69         struct snd_ice1712 *ice;
 70         struct snd_wm8776 wm[2];                   70         struct snd_wm8776 wm[2];
 71         struct mutex mutex;                        71         struct mutex mutex;
 72 };                                                 72 };
 73                                                    73 
 74                                                    74 
 75 /* write the given register and save the data      75 /* write the given register and save the data to the cache */
 76 static void wm8776_write(struct snd_ice1712 *i     76 static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
 77                          unsigned char reg, un     77                          unsigned char reg, unsigned short val)
 78 {                                                  78 {
 79         /*                                         79         /*
 80          * WM8776 registers are up to 9 bits w     80          * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
 81          * of the address field                    81          * of the address field
 82          */                                        82          */
 83         snd_vt1724_write_i2c(ice, wm->addr,        83         snd_vt1724_write_i2c(ice, wm->addr,
 84                              (reg << 1) | ((va     84                              (reg << 1) | ((val >> 8) & 1),
 85                              val & 0xff);          85                              val & 0xff);
 86         wm->regs[reg] = val;                       86         wm->regs[reg] = val;
 87 }                                                  87 }
 88                                                    88 
 89 /*                                                 89 /*
 90  * update the given register with and/or mask      90  * update the given register with and/or mask and save the data to the cache
 91  */                                                91  */
 92 static int wm8776_write_bits(struct snd_ice171     92 static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
 93                              unsigned char reg     93                              unsigned char reg,
 94                              unsigned short ma     94                              unsigned short mask, unsigned short val)
 95 {                                                  95 {
 96         val |= wm->regs[reg] & ~mask;              96         val |= wm->regs[reg] & ~mask;
 97         if (val != wm->regs[reg]) {                97         if (val != wm->regs[reg]) {
 98                 wm8776_write(ice, wm, reg, val     98                 wm8776_write(ice, wm, reg, val);
 99                 return 1;                          99                 return 1;
100         }                                         100         }
101         return 0;                                 101         return 0;
102 }                                                 102 }
103                                                   103 
104                                                   104 
105 /*                                                105 /*
106  * WM8776 volume controls                         106  * WM8776 volume controls
107  */                                               107  */
108                                                   108 
109 struct maya_vol_info {                            109 struct maya_vol_info {
110         unsigned int maxval;            /* vol    110         unsigned int maxval;            /* volume range: 0..maxval */
111         unsigned char regs[2];          /* lef    111         unsigned char regs[2];          /* left and right registers */
112         unsigned short mask;            /* val    112         unsigned short mask;            /* value mask */
113         unsigned short offset;          /* zer    113         unsigned short offset;          /* zero-value offset */
114         unsigned short mute;            /* mut    114         unsigned short mute;            /* mute bit */
115         unsigned short update;          /* upd    115         unsigned short update;          /* update bits */
116         unsigned char mux_bits[2];      /* ext    116         unsigned char mux_bits[2];      /* extra bits for ADC mute */
117 };                                                117 };
118                                                   118 
119 static const struct maya_vol_info vol_info[WM_    119 static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
120         [WM_VOL_HP] = {                           120         [WM_VOL_HP] = {
121                 .maxval = 80,                     121                 .maxval = 80,
122                 .regs = { WM8776_REG_HEADPHONE    122                 .regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
123                 .mask = 0x7f,                     123                 .mask = 0x7f,
124                 .offset = 0x30,                   124                 .offset = 0x30,
125                 .mute = 0x00,                     125                 .mute = 0x00,
126                 .update = 0x180,        /* upd    126                 .update = 0x180,        /* update and zero-cross enable */
127         },                                        127         },
128         [WM_VOL_DAC] = {                          128         [WM_VOL_DAC] = {
129                 .maxval = 255,                    129                 .maxval = 255,
130                 .regs = { WM8776_REG_DAC_ATTEN    130                 .regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
131                 .mask = 0xff,                     131                 .mask = 0xff,
132                 .offset = 0x01,                   132                 .offset = 0x01,
133                 .mute = 0x00,                     133                 .mute = 0x00,
134                 .update = 0x100,        /* zer    134                 .update = 0x100,        /* zero-cross enable */
135         },                                        135         },
136         [WM_VOL_ADC] = {                          136         [WM_VOL_ADC] = {
137                 .maxval = 91,                     137                 .maxval = 91,
138                 .regs = { WM8776_REG_ADC_ATTEN    138                 .regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
139                 .mask = 0xff,                     139                 .mask = 0xff,
140                 .offset = 0xa5,                   140                 .offset = 0xa5,
141                 .mute = 0xa5,                     141                 .mute = 0xa5,
142                 .update = 0x100,        /* upd    142                 .update = 0x100,        /* update */
143                 .mux_bits = { 0x80, 0x40 }, /*    143                 .mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
144         },                                        144         },
145 };                                                145 };
146                                                   146 
147 /*                                                147 /*
148  * dB tables                                      148  * dB tables
149  */                                               149  */
150 /* headphone output: mute, -73..+6db (1db step    150 /* headphone output: mute, -73..+6db (1db step) */
151 static const DECLARE_TLV_DB_SCALE(db_scale_hp,    151 static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
152 /* DAC output: mute, -127..0db (0.5db step) */    152 /* DAC output: mute, -127..0db (0.5db step) */
153 static const DECLARE_TLV_DB_SCALE(db_scale_dac    153 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
154 /* ADC gain: mute, -21..+24db (0.5db step) */     154 /* ADC gain: mute, -21..+24db (0.5db step) */
155 static const DECLARE_TLV_DB_SCALE(db_scale_adc    155 static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
156                                                   156 
157 static int maya_vol_info(struct snd_kcontrol *    157 static int maya_vol_info(struct snd_kcontrol *kcontrol,
158                          struct snd_ctl_elem_i    158                          struct snd_ctl_elem_info *uinfo)
159 {                                                 159 {
160         unsigned int idx = kcontrol->private_v    160         unsigned int idx = kcontrol->private_value;
161         const struct maya_vol_info *vol = &vol    161         const struct maya_vol_info *vol = &vol_info[idx];
162                                                   162 
163         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE    163         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
164         uinfo->count = 2;                         164         uinfo->count = 2;
165         uinfo->value.integer.min = 0;             165         uinfo->value.integer.min = 0;
166         uinfo->value.integer.max = vol->maxval    166         uinfo->value.integer.max = vol->maxval;
167         return 0;                                 167         return 0;
168 }                                                 168 }
169                                                   169 
170 static int maya_vol_get(struct snd_kcontrol *k    170 static int maya_vol_get(struct snd_kcontrol *kcontrol,
171                         struct snd_ctl_elem_va    171                         struct snd_ctl_elem_value *ucontrol)
172 {                                                 172 {
173         struct snd_maya44 *chip = snd_kcontrol    173         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
174         struct snd_wm8776 *wm =                   174         struct snd_wm8776 *wm =
175                 &chip->wm[snd_ctl_get_ioff(kco    175                 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
176         unsigned int idx = kcontrol->private_v    176         unsigned int idx = kcontrol->private_value;
177                                                   177 
178         mutex_lock(&chip->mutex);                 178         mutex_lock(&chip->mutex);
179         ucontrol->value.integer.value[0] = wm-    179         ucontrol->value.integer.value[0] = wm->volumes[idx][0];
180         ucontrol->value.integer.value[1] = wm-    180         ucontrol->value.integer.value[1] = wm->volumes[idx][1];
181         mutex_unlock(&chip->mutex);               181         mutex_unlock(&chip->mutex);
182         return 0;                                 182         return 0;
183 }                                                 183 }
184                                                   184 
185 static int maya_vol_put(struct snd_kcontrol *k    185 static int maya_vol_put(struct snd_kcontrol *kcontrol,
186                         struct snd_ctl_elem_va    186                         struct snd_ctl_elem_value *ucontrol)
187 {                                                 187 {
188         struct snd_maya44 *chip = snd_kcontrol    188         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
189         struct snd_wm8776 *wm =                   189         struct snd_wm8776 *wm =
190                 &chip->wm[snd_ctl_get_ioff(kco    190                 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
191         unsigned int idx = kcontrol->private_v    191         unsigned int idx = kcontrol->private_value;
192         const struct maya_vol_info *vol = &vol    192         const struct maya_vol_info *vol = &vol_info[idx];
193         unsigned int val, data;                   193         unsigned int val, data;
194         int ch, changed = 0;                      194         int ch, changed = 0;
195                                                   195 
196         mutex_lock(&chip->mutex);                 196         mutex_lock(&chip->mutex);
197         for (ch = 0; ch < 2; ch++) {              197         for (ch = 0; ch < 2; ch++) {
198                 val = ucontrol->value.integer.    198                 val = ucontrol->value.integer.value[ch];
199                 if (val > vol->maxval)            199                 if (val > vol->maxval)
200                         val = vol->maxval;        200                         val = vol->maxval;
201                 if (val == wm->volumes[idx][ch    201                 if (val == wm->volumes[idx][ch])
202                         continue;                 202                         continue;
203                 if (!val)                         203                 if (!val)
204                         data = vol->mute;         204                         data = vol->mute;
205                 else                              205                 else
206                         data = (val - 1) + vol    206                         data = (val - 1) + vol->offset;
207                 data |= vol->update;              207                 data |= vol->update;
208                 changed |= wm8776_write_bits(c    208                 changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
209                                              v    209                                              vol->mask | vol->update, data);
210                 if (vol->mux_bits[ch])            210                 if (vol->mux_bits[ch])
211                         wm8776_write_bits(chip    211                         wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
212                                           vol-    212                                           vol->mux_bits[ch],
213                                           val     213                                           val ? 0 : vol->mux_bits[ch]);
214                 wm->volumes[idx][ch] = val;       214                 wm->volumes[idx][ch] = val;
215         }                                         215         }
216         mutex_unlock(&chip->mutex);               216         mutex_unlock(&chip->mutex);
217         return changed;                           217         return changed;
218 }                                                 218 }
219                                                   219 
220 /*                                                220 /*
221  * WM8776 switch controls                         221  * WM8776 switch controls
222  */                                               222  */
223                                                   223 
224 #define COMPOSE_SW_VAL(idx, reg, mask)  ((idx)    224 #define COMPOSE_SW_VAL(idx, reg, mask)  ((idx) | ((reg) << 8) | ((mask) << 16))
225 #define GET_SW_VAL_IDX(val)     ((val) & 0xff)    225 #define GET_SW_VAL_IDX(val)     ((val) & 0xff)
226 #define GET_SW_VAL_REG(val)     (((val) >> 8)     226 #define GET_SW_VAL_REG(val)     (((val) >> 8) & 0xff)
227 #define GET_SW_VAL_MASK(val)    (((val) >> 16)    227 #define GET_SW_VAL_MASK(val)    (((val) >> 16) & 0xff)
228                                                   228 
229 #define maya_sw_info    snd_ctl_boolean_mono_i    229 #define maya_sw_info    snd_ctl_boolean_mono_info
230                                                   230 
231 static int maya_sw_get(struct snd_kcontrol *kc    231 static int maya_sw_get(struct snd_kcontrol *kcontrol,
232                        struct snd_ctl_elem_val    232                        struct snd_ctl_elem_value *ucontrol)
233 {                                                 233 {
234         struct snd_maya44 *chip = snd_kcontrol    234         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
235         struct snd_wm8776 *wm =                   235         struct snd_wm8776 *wm =
236                 &chip->wm[snd_ctl_get_ioff(kco    236                 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
237         unsigned int idx = GET_SW_VAL_IDX(kcon    237         unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
238                                                   238 
239         ucontrol->value.integer.value[0] = (wm    239         ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
240         return 0;                                 240         return 0;
241 }                                                 241 }
242                                                   242 
243 static int maya_sw_put(struct snd_kcontrol *kc    243 static int maya_sw_put(struct snd_kcontrol *kcontrol,
244                        struct snd_ctl_elem_val    244                        struct snd_ctl_elem_value *ucontrol)
245 {                                                 245 {
246         struct snd_maya44 *chip = snd_kcontrol    246         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
247         struct snd_wm8776 *wm =                   247         struct snd_wm8776 *wm =
248                 &chip->wm[snd_ctl_get_ioff(kco    248                 &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
249         unsigned int idx = GET_SW_VAL_IDX(kcon    249         unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
250         unsigned int mask, val;                   250         unsigned int mask, val;
251         int changed;                              251         int changed;
252                                                   252 
253         mutex_lock(&chip->mutex);                 253         mutex_lock(&chip->mutex);
254         mask = 1 << idx;                          254         mask = 1 << idx;
255         wm->switch_bits &= ~mask;                 255         wm->switch_bits &= ~mask;
256         val = ucontrol->value.integer.value[0]    256         val = ucontrol->value.integer.value[0];
257         if (val)                                  257         if (val)
258                 wm->switch_bits |= mask;          258                 wm->switch_bits |= mask;
259         mask = GET_SW_VAL_MASK(kcontrol->priva    259         mask = GET_SW_VAL_MASK(kcontrol->private_value);
260         changed = wm8776_write_bits(chip->ice,    260         changed = wm8776_write_bits(chip->ice, wm,
261                                     GET_SW_VAL    261                                     GET_SW_VAL_REG(kcontrol->private_value),
262                                     mask, val     262                                     mask, val ? mask : 0);
263         mutex_unlock(&chip->mutex);               263         mutex_unlock(&chip->mutex);
264         return changed;                           264         return changed;
265 }                                                 265 }
266                                                   266 
267 /*                                                267 /*
268  * GPIO pins (known ones for maya44)              268  * GPIO pins (known ones for maya44)
269  */                                               269  */
270 #define GPIO_PHANTOM_OFF        2                 270 #define GPIO_PHANTOM_OFF        2
271 #define GPIO_MIC_RELAY          4                 271 #define GPIO_MIC_RELAY          4
272 #define GPIO_SPDIF_IN_INV       5                 272 #define GPIO_SPDIF_IN_INV       5
273 #define GPIO_MUST_BE_0          7                 273 #define GPIO_MUST_BE_0          7
274                                                   274 
275 /*                                                275 /*
276  * GPIO switch controls                           276  * GPIO switch controls
277  */                                               277  */
278                                                   278 
279 #define COMPOSE_GPIO_VAL(shift, inv)    ((shif    279 #define COMPOSE_GPIO_VAL(shift, inv)    ((shift) | ((inv) << 8))
280 #define GET_GPIO_VAL_SHIFT(val)         ((val)    280 #define GET_GPIO_VAL_SHIFT(val)         ((val) & 0xff)
281 #define GET_GPIO_VAL_INV(val)           (((val    281 #define GET_GPIO_VAL_INV(val)           (((val) >> 8) & 1)
282                                                   282 
283 static int maya_set_gpio_bits(struct snd_ice17    283 static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
284                               unsigned int bit    284                               unsigned int bits)
285 {                                                 285 {
286         unsigned int data;                        286         unsigned int data;
287         data = snd_ice1712_gpio_read(ice);        287         data = snd_ice1712_gpio_read(ice);
288         if ((data & mask) == bits)                288         if ((data & mask) == bits)
289                 return 0;                         289                 return 0;
290         snd_ice1712_gpio_write(ice, (data & ~m    290         snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
291         return 1;                                 291         return 1;
292 }                                                 292 }
293                                                   293 
294 #define maya_gpio_sw_info       snd_ctl_boolea    294 #define maya_gpio_sw_info       snd_ctl_boolean_mono_info
295                                                   295 
296 static int maya_gpio_sw_get(struct snd_kcontro    296 static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
297                             struct snd_ctl_ele    297                             struct snd_ctl_elem_value *ucontrol)
298 {                                                 298 {
299         struct snd_maya44 *chip = snd_kcontrol    299         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
300         unsigned int shift = GET_GPIO_VAL_SHIF    300         unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
301         unsigned int val;                         301         unsigned int val;
302                                                   302 
303         val = (snd_ice1712_gpio_read(chip->ice    303         val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
304         if (GET_GPIO_VAL_INV(kcontrol->private    304         if (GET_GPIO_VAL_INV(kcontrol->private_value))
305                 val = !val;                       305                 val = !val;
306         ucontrol->value.integer.value[0] = val    306         ucontrol->value.integer.value[0] = val;
307         return 0;                                 307         return 0;
308 }                                                 308 }
309                                                   309 
310 static int maya_gpio_sw_put(struct snd_kcontro    310 static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
311                             struct snd_ctl_ele    311                             struct snd_ctl_elem_value *ucontrol)
312 {                                                 312 {
313         struct snd_maya44 *chip = snd_kcontrol    313         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
314         unsigned int shift = GET_GPIO_VAL_SHIF    314         unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
315         unsigned int val, mask;                   315         unsigned int val, mask;
316         int changed;                              316         int changed;
317                                                   317 
318         mutex_lock(&chip->mutex);                 318         mutex_lock(&chip->mutex);
319         mask = 1 << shift;                        319         mask = 1 << shift;
320         val = ucontrol->value.integer.value[0]    320         val = ucontrol->value.integer.value[0];
321         if (GET_GPIO_VAL_INV(kcontrol->private    321         if (GET_GPIO_VAL_INV(kcontrol->private_value))
322                 val = !val;                       322                 val = !val;
323         val = val ? mask : 0;                     323         val = val ? mask : 0;
324         changed = maya_set_gpio_bits(chip->ice    324         changed = maya_set_gpio_bits(chip->ice, mask, val);
325         mutex_unlock(&chip->mutex);               325         mutex_unlock(&chip->mutex);
326         return changed;                           326         return changed;
327 }                                                 327 }
328                                                   328 
329 /*                                                329 /*
330  * capture source selection                       330  * capture source selection
331  */                                               331  */
332                                                   332 
333 /* known working input slots (0-4) */             333 /* known working input slots (0-4) */
334 #define MAYA_LINE_IN    1       /* in-2 */        334 #define MAYA_LINE_IN    1       /* in-2 */
335 #define MAYA_MIC_IN     3       /* in-4 */        335 #define MAYA_MIC_IN     3       /* in-4 */
336                                                   336 
337 static void wm8776_select_input(struct snd_may    337 static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
338 {                                                 338 {
339         wm8776_write_bits(chip->ice, &chip->wm    339         wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
340                           0x1f, 1 << line);       340                           0x1f, 1 << line);
341 }                                                 341 }
342                                                   342 
343 static int maya_rec_src_info(struct snd_kcontr    343 static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
344                              struct snd_ctl_el    344                              struct snd_ctl_elem_info *uinfo)
345 {                                                 345 {
346         static const char * const texts[] = {     346         static const char * const texts[] = { "Line", "Mic" };
347                                                   347 
348         return snd_ctl_enum_info(uinfo, 1, ARR    348         return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
349 }                                                 349 }
350                                                   350 
351 static int maya_rec_src_get(struct snd_kcontro    351 static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
352                             struct snd_ctl_ele    352                             struct snd_ctl_elem_value *ucontrol)
353 {                                                 353 {
354         struct snd_maya44 *chip = snd_kcontrol    354         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
355         int sel;                                  355         int sel;
356                                                   356 
357         if (snd_ice1712_gpio_read(chip->ice) &    357         if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
358                 sel = 1;                          358                 sel = 1;
359         else                                      359         else
360                 sel = 0;                          360                 sel = 0;
361         ucontrol->value.enumerated.item[0] = s    361         ucontrol->value.enumerated.item[0] = sel;
362         return 0;                                 362         return 0;
363 }                                                 363 }
364                                                   364 
365 static int maya_rec_src_put(struct snd_kcontro    365 static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
366                             struct snd_ctl_ele    366                             struct snd_ctl_elem_value *ucontrol)
367 {                                                 367 {
368         struct snd_maya44 *chip = snd_kcontrol    368         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
369         int sel = ucontrol->value.enumerated.i    369         int sel = ucontrol->value.enumerated.item[0];
370         int changed;                              370         int changed;
371                                                   371 
372         mutex_lock(&chip->mutex);                 372         mutex_lock(&chip->mutex);
373         changed = maya_set_gpio_bits(chip->ice    373         changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
374                                      sel ? (1     374                                      sel ? (1 << GPIO_MIC_RELAY) : 0);
375         wm8776_select_input(chip, 0, sel ? MAY    375         wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
376         mutex_unlock(&chip->mutex);               376         mutex_unlock(&chip->mutex);
377         return changed;                           377         return changed;
378 }                                                 378 }
379                                                   379 
380 /*                                                380 /*
381  * Maya44 routing switch settings have differe    381  * Maya44 routing switch settings have different meanings than the standard
382  * ice1724 switches as defined in snd_vt1724_p    382  * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
383  */                                               383  */
384 static int maya_pb_route_info(struct snd_kcont    384 static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
385                               struct snd_ctl_e    385                               struct snd_ctl_elem_info *uinfo)
386 {                                                 386 {
387         static const char * const texts[] = {     387         static const char * const texts[] = {
388                 "PCM Out", /* 0 */                388                 "PCM Out", /* 0 */
389                 "Input 1", "Input 2", "Input 3    389                 "Input 1", "Input 2", "Input 3", "Input 4"
390         };                                        390         };
391                                                   391 
392         return snd_ctl_enum_info(uinfo, 1, ARR    392         return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
393 }                                                 393 }
394                                                   394 
395 static int maya_pb_route_shift(int idx)           395 static int maya_pb_route_shift(int idx)
396 {                                                 396 {
397         static const unsigned char shift[10] =    397         static const unsigned char shift[10] =
398                 { 8, 20, 0, 3, 11, 23, 14, 26,    398                 { 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
399         return shift[idx % 10];                   399         return shift[idx % 10];
400 }                                                 400 }
401                                                   401 
402 static int maya_pb_route_get(struct snd_kcontr    402 static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
403                              struct snd_ctl_el    403                              struct snd_ctl_elem_value *ucontrol)
404 {                                                 404 {
405         struct snd_maya44 *chip = snd_kcontrol    405         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
406         int idx = snd_ctl_get_ioffidx(kcontrol    406         int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
407         ucontrol->value.enumerated.item[0] =      407         ucontrol->value.enumerated.item[0] =
408                 snd_ice1724_get_route_val(chip    408                 snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
409         return 0;                                 409         return 0;
410 }                                                 410 }
411                                                   411 
412 static int maya_pb_route_put(struct snd_kcontr    412 static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
413                              struct snd_ctl_el    413                              struct snd_ctl_elem_value *ucontrol)
414 {                                                 414 {
415         struct snd_maya44 *chip = snd_kcontrol    415         struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
416         int idx = snd_ctl_get_ioffidx(kcontrol    416         int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
417         return snd_ice1724_put_route_val(chip-    417         return snd_ice1724_put_route_val(chip->ice,
418                                          ucont    418                                          ucontrol->value.enumerated.item[0],
419                                          maya_    419                                          maya_pb_route_shift(idx));
420 }                                                 420 }
421                                                   421 
422                                                   422 
423 /*                                                423 /*
424  * controls to be added                           424  * controls to be added
425  */                                               425  */
426                                                   426 
427 static const struct snd_kcontrol_new maya_cont    427 static const struct snd_kcontrol_new maya_controls[] = {
428         {                                         428         {
429                 .name = "Crossmix Playback Vol    429                 .name = "Crossmix Playback Volume",
430                 .iface = SNDRV_CTL_ELEM_IFACE_    430                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
431                 .access = SNDRV_CTL_ELEM_ACCES    431                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
432                         SNDRV_CTL_ELEM_ACCESS_    432                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
433                 .info = maya_vol_info,            433                 .info = maya_vol_info,
434                 .get = maya_vol_get,              434                 .get = maya_vol_get,
435                 .put = maya_vol_put,              435                 .put = maya_vol_put,
436                 .tlv = { .p = db_scale_hp },      436                 .tlv = { .p = db_scale_hp },
437                 .private_value = WM_VOL_HP,       437                 .private_value = WM_VOL_HP,
438                 .count = 2,                       438                 .count = 2,
439         },                                        439         },
440         {                                         440         {
441                 .name = "PCM Playback Volume",    441                 .name = "PCM Playback Volume",
442                 .iface = SNDRV_CTL_ELEM_IFACE_    442                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
443                 .access = SNDRV_CTL_ELEM_ACCES    443                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
444                         SNDRV_CTL_ELEM_ACCESS_    444                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
445                 .info = maya_vol_info,            445                 .info = maya_vol_info,
446                 .get = maya_vol_get,              446                 .get = maya_vol_get,
447                 .put = maya_vol_put,              447                 .put = maya_vol_put,
448                 .tlv = { .p = db_scale_dac },     448                 .tlv = { .p = db_scale_dac },
449                 .private_value = WM_VOL_DAC,      449                 .private_value = WM_VOL_DAC,
450                 .count = 2,                       450                 .count = 2,
451         },                                        451         },
452         {                                         452         {
453                 .name = "Line Capture Volume",    453                 .name = "Line Capture Volume",
454                 .iface = SNDRV_CTL_ELEM_IFACE_    454                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
455                 .access = SNDRV_CTL_ELEM_ACCES    455                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
456                         SNDRV_CTL_ELEM_ACCESS_    456                         SNDRV_CTL_ELEM_ACCESS_TLV_READ,
457                 .info = maya_vol_info,            457                 .info = maya_vol_info,
458                 .get = maya_vol_get,              458                 .get = maya_vol_get,
459                 .put = maya_vol_put,              459                 .put = maya_vol_put,
460                 .tlv = { .p = db_scale_adc },     460                 .tlv = { .p = db_scale_adc },
461                 .private_value = WM_VOL_ADC,      461                 .private_value = WM_VOL_ADC,
462                 .count = 2,                       462                 .count = 2,
463         },                                        463         },
464         {                                         464         {
465                 .name = "PCM Playback Switch",    465                 .name = "PCM Playback Switch",
466                 .iface = SNDRV_CTL_ELEM_IFACE_    466                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
467                 .info = maya_sw_info,             467                 .info = maya_sw_info,
468                 .get = maya_sw_get,               468                 .get = maya_sw_get,
469                 .put = maya_sw_put,               469                 .put = maya_sw_put,
470                 .private_value = COMPOSE_SW_VA    470                 .private_value = COMPOSE_SW_VAL(WM_SW_DAC,
471                                                   471                                                 WM8776_REG_OUTPUT_MUX, 0x01),
472                 .count = 2,                       472                 .count = 2,
473         },                                        473         },
474         {                                         474         {
475                 .name = "Bypass Playback Switc    475                 .name = "Bypass Playback Switch",
476                 .iface = SNDRV_CTL_ELEM_IFACE_    476                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
477                 .info = maya_sw_info,             477                 .info = maya_sw_info,
478                 .get = maya_sw_get,               478                 .get = maya_sw_get,
479                 .put = maya_sw_put,               479                 .put = maya_sw_put,
480                 .private_value = COMPOSE_SW_VA    480                 .private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
481                                                   481                                                 WM8776_REG_OUTPUT_MUX, 0x04),
482                 .count = 2,                       482                 .count = 2,
483         },                                        483         },
484         {                                         484         {
485                 .name = "Capture Source",         485                 .name = "Capture Source",
486                 .iface = SNDRV_CTL_ELEM_IFACE_    486                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
487                 .info = maya_rec_src_info,        487                 .info = maya_rec_src_info,
488                 .get = maya_rec_src_get,          488                 .get = maya_rec_src_get,
489                 .put = maya_rec_src_put,          489                 .put = maya_rec_src_put,
490         },                                        490         },
491         {                                         491         {
492                 .name = "Mic Phantom Power Swi    492                 .name = "Mic Phantom Power Switch",
493                 .iface = SNDRV_CTL_ELEM_IFACE_    493                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
494                 .info = maya_gpio_sw_info,        494                 .info = maya_gpio_sw_info,
495                 .get = maya_gpio_sw_get,          495                 .get = maya_gpio_sw_get,
496                 .put = maya_gpio_sw_put,          496                 .put = maya_gpio_sw_put,
497                 .private_value = COMPOSE_GPIO_    497                 .private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
498         },                                        498         },
499         {                                         499         {
500                 .name = "SPDIF Capture Switch"    500                 .name = "SPDIF Capture Switch",
501                 .iface = SNDRV_CTL_ELEM_IFACE_    501                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
502                 .info = maya_gpio_sw_info,        502                 .info = maya_gpio_sw_info,
503                 .get = maya_gpio_sw_get,          503                 .get = maya_gpio_sw_get,
504                 .put = maya_gpio_sw_put,          504                 .put = maya_gpio_sw_put,
505                 .private_value = COMPOSE_GPIO_    505                 .private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
506         },                                        506         },
507         {                                         507         {
508                 .iface = SNDRV_CTL_ELEM_IFACE_    508                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
509                 .name = "H/W Playback Route",     509                 .name = "H/W Playback Route",
510                 .info = maya_pb_route_info,       510                 .info = maya_pb_route_info,
511                 .get = maya_pb_route_get,         511                 .get = maya_pb_route_get,
512                 .put = maya_pb_route_put,         512                 .put = maya_pb_route_put,
513                 .count = 4,  /* FIXME: do cont    513                 .count = 4,  /* FIXME: do controls 5-9 have any meaning? */
514         },                                        514         },
515 };                                                515 };
516                                                   516 
517 static int maya44_add_controls(struct snd_ice1    517 static int maya44_add_controls(struct snd_ice1712 *ice)
518 {                                                 518 {
519         int err, i;                               519         int err, i;
520                                                   520 
521         for (i = 0; i < ARRAY_SIZE(maya_contro    521         for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
522                 err = snd_ctl_add(ice->card, s    522                 err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
523                                                   523                                                           ice->spec));
524                 if (err < 0)                      524                 if (err < 0)
525                         return err;               525                         return err;
526         }                                         526         }
527         return 0;                                 527         return 0;
528 }                                                 528 }
529                                                   529 
530                                                   530 
531 /*                                                531 /*
532  * initialize a wm8776 chip                       532  * initialize a wm8776 chip
533  */                                               533  */
534 static void wm8776_init(struct snd_ice1712 *ic    534 static void wm8776_init(struct snd_ice1712 *ice,
535                         struct snd_wm8776 *wm,    535                         struct snd_wm8776 *wm, unsigned int addr)
536 {                                                 536 {
537         static const unsigned short inits_wm87    537         static const unsigned short inits_wm8776[] = {
538                 0x02, 0x100, /* R2: headphone     538                 0x02, 0x100, /* R2: headphone L+R muted + update */
539                 0x05, 0x100, /* R5: DAC output    539                 0x05, 0x100, /* R5: DAC output L+R muted + update */
540                 0x06, 0x000, /* R6: DAC output    540                 0x06, 0x000, /* R6: DAC output phase normal */
541                 0x07, 0x091, /* R7: DAC enable    541                 0x07, 0x091, /* R7: DAC enable zero cross detection,
542                                 normal output     542                                 normal output */
543                 0x08, 0x000, /* R8: DAC soft m    543                 0x08, 0x000, /* R8: DAC soft mute off */
544                 0x09, 0x000, /* R9: no deemph,    544                 0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
545                 0x0a, 0x022, /* R10: DAC I2C m    545                 0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
546                 0x0b, 0x022, /* R11: ADC I2C m    546                 0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
547                                 highpass filte    547                                 highpass filter enabled */
548                 0x0c, 0x042, /* R12: ADC+DAC s    548                 0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
549                 0x0d, 0x000, /* R13: all power    549                 0x0d, 0x000, /* R13: all power up */
550                 0x0e, 0x100, /* R14: ADC left     550                 0x0e, 0x100, /* R14: ADC left muted,
551                                 enable zero cr    551                                 enable zero cross detection */
552                 0x0f, 0x100, /* R15: ADC right    552                 0x0f, 0x100, /* R15: ADC right muted,
553                                 enable zero cr    553                                 enable zero cross detection */
554                              /* R16: ALC...*/     554                              /* R16: ALC...*/
555                 0x11, 0x000, /* R17: disable A    555                 0x11, 0x000, /* R17: disable ALC */
556                              /* R18: ALC...*/     556                              /* R18: ALC...*/
557                              /* R19: noise gat    557                              /* R19: noise gate...*/
558                 0x15, 0x000, /* R21: ADC input    558                 0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
559                 0x16, 0x001, /* R22: output mu    559                 0x16, 0x001, /* R22: output mux, select DAC */
560                 0xff, 0xff                        560                 0xff, 0xff
561         };                                        561         };
562                                                   562 
563         const unsigned short *ptr;                563         const unsigned short *ptr;
564         unsigned char reg;                        564         unsigned char reg;
565         unsigned short data;                      565         unsigned short data;
566                                                   566 
567         wm->addr = addr;                          567         wm->addr = addr;
568         /* enable DAC output; mute bypass, aux    568         /* enable DAC output; mute bypass, aux & all inputs */
569         wm->switch_bits = (1 << WM_SW_DAC);       569         wm->switch_bits = (1 << WM_SW_DAC);
570                                                   570 
571         ptr = inits_wm8776;                       571         ptr = inits_wm8776;
572         while (*ptr != 0xff) {                    572         while (*ptr != 0xff) {
573                 reg = *ptr++;                     573                 reg = *ptr++;
574                 data = *ptr++;                    574                 data = *ptr++;
575                 wm8776_write(ice, wm, reg, dat    575                 wm8776_write(ice, wm, reg, data);
576         }                                         576         }
577 }                                                 577 }
578                                                   578 
579                                                   579 
580 /*                                                580 /*
581  * change the rate on the WM8776 codecs.          581  * change the rate on the WM8776 codecs.
582  * this assumes that the VT17xx's rate is chan    582  * this assumes that the VT17xx's rate is changed by the calling function.
583  * NOTE: even though the WM8776's are running     583  * NOTE: even though the WM8776's are running in slave mode and rate
584  * selection is automatic, we need to call snd    584  * selection is automatic, we need to call snd_wm8776_set_rate() here
585  * to make sure some flags are set correctly.     585  * to make sure some flags are set correctly.
586  */                                               586  */
587 static void set_rate(struct snd_ice1712 *ice,     587 static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
588 {                                                 588 {
589         struct snd_maya44 *chip = ice->spec;      589         struct snd_maya44 *chip = ice->spec;
590         unsigned int ratio, adc_ratio, val;       590         unsigned int ratio, adc_ratio, val;
591         int i;                                    591         int i;
592                                                   592 
593         switch (rate) {                           593         switch (rate) {
594         case 192000:                              594         case 192000:
595                 ratio = WM8776_CLOCK_RATIO_128    595                 ratio = WM8776_CLOCK_RATIO_128FS;
596                 break;                            596                 break;
597         case 176400:                              597         case 176400:
598                 ratio = WM8776_CLOCK_RATIO_128    598                 ratio = WM8776_CLOCK_RATIO_128FS;
599                 break;                            599                 break;
600         case 96000:                               600         case 96000:
601                 ratio = WM8776_CLOCK_RATIO_256    601                 ratio = WM8776_CLOCK_RATIO_256FS;
602                 break;                            602                 break;
603         case 88200:                               603         case 88200:
604                 ratio = WM8776_CLOCK_RATIO_384    604                 ratio = WM8776_CLOCK_RATIO_384FS;
605                 break;                            605                 break;
606         case 48000:                               606         case 48000:
607                 ratio = WM8776_CLOCK_RATIO_512    607                 ratio = WM8776_CLOCK_RATIO_512FS;
608                 break;                            608                 break;
609         case 44100:                               609         case 44100:
610                 ratio = WM8776_CLOCK_RATIO_512    610                 ratio = WM8776_CLOCK_RATIO_512FS;
611                 break;                            611                 break;
612         case 32000:                               612         case 32000:
613                 ratio = WM8776_CLOCK_RATIO_768    613                 ratio = WM8776_CLOCK_RATIO_768FS;
614                 break;                            614                 break;
615         case 0:                                   615         case 0:
616                 /* no hint - S/PDIF input is m    616                 /* no hint - S/PDIF input is master, simply return */
617                 return;                           617                 return;
618         default:                                  618         default:
619                 snd_BUG();                        619                 snd_BUG();
620                 return;                           620                 return;
621         }                                         621         }
622                                                   622 
623         /*                                        623         /*
624          * this currently sets the same rate f    624          * this currently sets the same rate for ADC and DAC, but limits
625          * ADC rate to 256X (96kHz). For 256X     625          * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
626          * oversampling to 64x, as recommended    626          * oversampling to 64x, as recommended by WM8776 datasheet.
627          * Setting the rate is not really nece    627          * Setting the rate is not really necessary in slave mode.
628          */                                       628          */
629         adc_ratio = ratio;                        629         adc_ratio = ratio;
630         if (adc_ratio < WM8776_CLOCK_RATIO_256    630         if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
631                 adc_ratio = WM8776_CLOCK_RATIO    631                 adc_ratio = WM8776_CLOCK_RATIO_256FS;
632                                                   632 
633         val = adc_ratio;                          633         val = adc_ratio;
634         if (adc_ratio == WM8776_CLOCK_RATIO_25    634         if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
635                 val |= 8;                         635                 val |= 8;
636         val |= ratio << 4;                        636         val |= ratio << 4;
637                                                   637 
638         mutex_lock(&chip->mutex);                 638         mutex_lock(&chip->mutex);
639         for (i = 0; i < 2; i++)                   639         for (i = 0; i < 2; i++)
640                 wm8776_write_bits(ice, &chip->    640                 wm8776_write_bits(ice, &chip->wm[i],
641                                   WM8776_REG_M    641                                   WM8776_REG_MASTER_MODE_CONTROL,
642                                   0x180, val);    642                                   0x180, val);
643         mutex_unlock(&chip->mutex);               643         mutex_unlock(&chip->mutex);
644 }                                                 644 }
645                                                   645 
646 /*                                                646 /*
647  * supported sample rates (to override the def    647  * supported sample rates (to override the default one)
648  */                                               648  */
649                                                   649 
650 static const unsigned int rates[] = {             650 static const unsigned int rates[] = {
651         32000, 44100, 48000, 64000, 88200, 960    651         32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
652 };                                                652 };
653                                                   653 
654 /* playback rates: 32..192 kHz */                 654 /* playback rates: 32..192 kHz */
655 static const struct snd_pcm_hw_constraint_list    655 static const struct snd_pcm_hw_constraint_list dac_rates = {
656         .count = ARRAY_SIZE(rates),               656         .count = ARRAY_SIZE(rates),
657         .list = rates,                            657         .list = rates,
658         .mask = 0                                 658         .mask = 0
659 };                                                659 };
660                                                   660 
661                                                   661 
662 /*                                                662 /*
663  * chip addresses on I2C bus                      663  * chip addresses on I2C bus
664  */                                               664  */
665 static const unsigned char wm8776_addr[2] = {     665 static const unsigned char wm8776_addr[2] = {
666         0x34, 0x36, /* codec 0 & 1 */             666         0x34, 0x36, /* codec 0 & 1 */
667 };                                                667 };
668                                                   668 
669 /*                                                669 /*
670  * initialize the chip                            670  * initialize the chip
671  */                                               671  */
672 static int maya44_init(struct snd_ice1712 *ice    672 static int maya44_init(struct snd_ice1712 *ice)
673 {                                                 673 {
674         int i;                                    674         int i;
675         struct snd_maya44 *chip;                  675         struct snd_maya44 *chip;
676                                                   676 
677         chip = kzalloc(sizeof(*chip), GFP_KERN    677         chip = kzalloc(sizeof(*chip), GFP_KERNEL);
678         if (!chip)                                678         if (!chip)
679                 return -ENOMEM;                   679                 return -ENOMEM;
680         mutex_init(&chip->mutex);                 680         mutex_init(&chip->mutex);
681         chip->ice = ice;                          681         chip->ice = ice;
682         ice->spec = chip;                         682         ice->spec = chip;
683                                                   683 
684         /* initialise codecs */                   684         /* initialise codecs */
685         ice->num_total_dacs = 4;                  685         ice->num_total_dacs = 4;
686         ice->num_total_adcs = 4;                  686         ice->num_total_adcs = 4;
687         ice->akm_codecs = 0;                      687         ice->akm_codecs = 0;
688                                                   688 
689         for (i = 0; i < 2; i++) {                 689         for (i = 0; i < 2; i++) {
690                 wm8776_init(ice, &chip->wm[i],    690                 wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
691                 wm8776_select_input(chip, i, M    691                 wm8776_select_input(chip, i, MAYA_LINE_IN);
692         }                                         692         }
693                                                   693 
694         /* set card specific rates */             694         /* set card specific rates */
695         ice->hw_rates = &dac_rates;               695         ice->hw_rates = &dac_rates;
696                                                   696 
697         /* register change rate notifier */       697         /* register change rate notifier */
698         ice->gpio.set_pro_rate = set_rate;        698         ice->gpio.set_pro_rate = set_rate;
699                                                   699 
700         /* RDMA1 (2nd input channel) is used f    700         /* RDMA1 (2nd input channel) is used for ADC by default */
701         ice->force_rdma1 = 1;                     701         ice->force_rdma1 = 1;
702                                                   702 
703         /* have an own routing control */         703         /* have an own routing control */
704         ice->own_routing = 1;                     704         ice->own_routing = 1;
705                                                   705 
706         return 0;                                 706         return 0;
707 }                                                 707 }
708                                                   708 
709                                                   709 
710 /*                                                710 /*
711  * Maya44 boards don't provide the EEPROM data    711  * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
712  * hence the driver needs to sets up it proper    712  * hence the driver needs to sets up it properly.
713  */                                               713  */
714                                                   714 
715 static const unsigned char maya44_eeprom[] = {    715 static const unsigned char maya44_eeprom[] = {
716         [ICE_EEP2_SYSCONF]     = 0x45,            716         [ICE_EEP2_SYSCONF]     = 0x45,
717                 /* clock xin1=49.152MHz, mpu40    717                 /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
718         [ICE_EEP2_ACLINK]      = 0x80,            718         [ICE_EEP2_ACLINK]      = 0x80,
719                 /* I2S */                         719                 /* I2S */
720         [ICE_EEP2_I2S]         = 0xf8,            720         [ICE_EEP2_I2S]         = 0xf8,
721                 /* vol, 96k, 24bit, 192k */       721                 /* vol, 96k, 24bit, 192k */
722         [ICE_EEP2_SPDIF]       = 0xc3,            722         [ICE_EEP2_SPDIF]       = 0xc3,
723                 /* enable spdif out, spdif out    723                 /* enable spdif out, spdif out supp, spdif-in, ext spdif out */
724         [ICE_EEP2_GPIO_DIR]    = 0xff,            724         [ICE_EEP2_GPIO_DIR]    = 0xff,
725         [ICE_EEP2_GPIO_DIR1]   = 0xff,            725         [ICE_EEP2_GPIO_DIR1]   = 0xff,
726         [ICE_EEP2_GPIO_DIR2]   = 0xff,            726         [ICE_EEP2_GPIO_DIR2]   = 0xff,
727         [ICE_EEP2_GPIO_MASK]   = 0/*0x9f*/,       727         [ICE_EEP2_GPIO_MASK]   = 0/*0x9f*/,
728         [ICE_EEP2_GPIO_MASK1]  = 0/*0xff*/,       728         [ICE_EEP2_GPIO_MASK1]  = 0/*0xff*/,
729         [ICE_EEP2_GPIO_MASK2]  = 0/*0x7f*/,       729         [ICE_EEP2_GPIO_MASK2]  = 0/*0x7f*/,
730         [ICE_EEP2_GPIO_STATE]  = (1 << GPIO_PH    730         [ICE_EEP2_GPIO_STATE]  = (1 << GPIO_PHANTOM_OFF) |
731                         (1 << GPIO_SPDIF_IN_IN    731                         (1 << GPIO_SPDIF_IN_INV),
732         [ICE_EEP2_GPIO_STATE1] = 0x00,            732         [ICE_EEP2_GPIO_STATE1] = 0x00,
733         [ICE_EEP2_GPIO_STATE2] = 0x00,            733         [ICE_EEP2_GPIO_STATE2] = 0x00,
734 };                                                734 };
735                                                   735 
736 /* entry point */                                 736 /* entry point */
737 struct snd_ice1712_card_info snd_vt1724_maya44    737 struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
738         {                                         738         {
739                 .subvendor = VT1724_SUBDEVICE_    739                 .subvendor = VT1724_SUBDEVICE_MAYA44,
740                 .name = "ESI Maya44",             740                 .name = "ESI Maya44",
741                 .model = "maya44",                741                 .model = "maya44",
742                 .chip_init = maya44_init,         742                 .chip_init = maya44_init,
743                 .build_controls = maya44_add_c    743                 .build_controls = maya44_add_controls,
744                 .eeprom_size = sizeof(maya44_e    744                 .eeprom_size = sizeof(maya44_eeprom),
745                 .eeprom_data = maya44_eeprom,     745                 .eeprom_data = maya44_eeprom,
746         },                                        746         },
747         { } /* terminator */                      747         { } /* terminator */
748 };                                                748 };
749                                                   749 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php