Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
0004  *
0005  *   Lowlevel functions for ESI Maya44 cards
0006  *
0007  *  Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
0008  *  Based on the patches by Rainer Zimmermann <mail@lightshed.de>
0009  */
0010 
0011 #include <linux/init.h>
0012 #include <linux/slab.h>
0013 #include <sound/core.h>
0014 #include <sound/control.h>
0015 #include <sound/pcm.h>
0016 #include <sound/tlv.h>
0017 
0018 #include "ice1712.h"
0019 #include "envy24ht.h"
0020 #include "maya44.h"
0021 
0022 /* WM8776 register indexes */
0023 #define WM8776_REG_HEADPHONE_L      0x00
0024 #define WM8776_REG_HEADPHONE_R      0x01
0025 #define WM8776_REG_HEADPHONE_MASTER 0x02
0026 #define WM8776_REG_DAC_ATTEN_L      0x03
0027 #define WM8776_REG_DAC_ATTEN_R      0x04
0028 #define WM8776_REG_DAC_ATTEN_MASTER 0x05
0029 #define WM8776_REG_DAC_PHASE        0x06
0030 #define WM8776_REG_DAC_CONTROL      0x07
0031 #define WM8776_REG_DAC_MUTE     0x08
0032 #define WM8776_REG_DAC_DEEMPH       0x09
0033 #define WM8776_REG_DAC_IF_CONTROL   0x0a
0034 #define WM8776_REG_ADC_IF_CONTROL   0x0b
0035 #define WM8776_REG_MASTER_MODE_CONTROL  0x0c
0036 #define WM8776_REG_POWERDOWN        0x0d
0037 #define WM8776_REG_ADC_ATTEN_L      0x0e
0038 #define WM8776_REG_ADC_ATTEN_R      0x0f
0039 #define WM8776_REG_ADC_ALC1     0x10
0040 #define WM8776_REG_ADC_ALC2     0x11
0041 #define WM8776_REG_ADC_ALC3     0x12
0042 #define WM8776_REG_ADC_NOISE_GATE   0x13
0043 #define WM8776_REG_ADC_LIMITER      0x14
0044 #define WM8776_REG_ADC_MUX      0x15
0045 #define WM8776_REG_OUTPUT_MUX       0x16
0046 #define WM8776_REG_RESET        0x17
0047 
0048 #define WM8776_NUM_REGS         0x18
0049 
0050 /* clock ratio identifiers for snd_wm8776_set_rate() */
0051 #define WM8776_CLOCK_RATIO_128FS    0
0052 #define WM8776_CLOCK_RATIO_192FS    1
0053 #define WM8776_CLOCK_RATIO_256FS    2
0054 #define WM8776_CLOCK_RATIO_384FS    3
0055 #define WM8776_CLOCK_RATIO_512FS    4
0056 #define WM8776_CLOCK_RATIO_768FS    5
0057 
0058 enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
0059 enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
0060 
0061 struct snd_wm8776 {
0062     unsigned char addr;
0063     unsigned short regs[WM8776_NUM_REGS];
0064     unsigned char volumes[WM_NUM_VOLS][2];
0065     unsigned int switch_bits;
0066 };
0067 
0068 struct snd_maya44 {
0069     struct snd_ice1712 *ice;
0070     struct snd_wm8776 wm[2];
0071     struct mutex mutex;
0072 };
0073 
0074 
0075 /* write the given register and save the data to the cache */
0076 static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
0077              unsigned char reg, unsigned short val)
0078 {
0079     /*
0080      * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
0081      * of the address field
0082      */
0083     snd_vt1724_write_i2c(ice, wm->addr,
0084                  (reg << 1) | ((val >> 8) & 1),
0085                  val & 0xff);
0086     wm->regs[reg] = val;
0087 }
0088 
0089 /*
0090  * update the given register with and/or mask and save the data to the cache
0091  */
0092 static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
0093                  unsigned char reg,
0094                  unsigned short mask, unsigned short val)
0095 {
0096     val |= wm->regs[reg] & ~mask;
0097     if (val != wm->regs[reg]) {
0098         wm8776_write(ice, wm, reg, val);
0099         return 1;
0100     }
0101     return 0;
0102 }
0103 
0104 
0105 /*
0106  * WM8776 volume controls
0107  */
0108 
0109 struct maya_vol_info {
0110     unsigned int maxval;        /* volume range: 0..maxval */
0111     unsigned char regs[2];      /* left and right registers */
0112     unsigned short mask;        /* value mask */
0113     unsigned short offset;      /* zero-value offset */
0114     unsigned short mute;        /* mute bit */
0115     unsigned short update;      /* update bits */
0116     unsigned char mux_bits[2];  /* extra bits for ADC mute */
0117 };
0118 
0119 static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
0120     [WM_VOL_HP] = {
0121         .maxval = 80,
0122         .regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
0123         .mask = 0x7f,
0124         .offset = 0x30,
0125         .mute = 0x00,
0126         .update = 0x180,    /* update and zero-cross enable */
0127     },
0128     [WM_VOL_DAC] = {
0129         .maxval = 255,
0130         .regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
0131         .mask = 0xff,
0132         .offset = 0x01,
0133         .mute = 0x00,
0134         .update = 0x100,    /* zero-cross enable */
0135     },
0136     [WM_VOL_ADC] = {
0137         .maxval = 91,
0138         .regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
0139         .mask = 0xff,
0140         .offset = 0xa5,
0141         .mute = 0xa5,
0142         .update = 0x100,    /* update */
0143         .mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
0144     },
0145 };
0146 
0147 /*
0148  * dB tables
0149  */
0150 /* headphone output: mute, -73..+6db (1db step) */
0151 static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
0152 /* DAC output: mute, -127..0db (0.5db step) */
0153 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
0154 /* ADC gain: mute, -21..+24db (0.5db step) */
0155 static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
0156 
0157 static int maya_vol_info(struct snd_kcontrol *kcontrol,
0158              struct snd_ctl_elem_info *uinfo)
0159 {
0160     unsigned int idx = kcontrol->private_value;
0161     const struct maya_vol_info *vol = &vol_info[idx];
0162 
0163     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0164     uinfo->count = 2;
0165     uinfo->value.integer.min = 0;
0166     uinfo->value.integer.max = vol->maxval;
0167     return 0;
0168 }
0169 
0170 static int maya_vol_get(struct snd_kcontrol *kcontrol,
0171             struct snd_ctl_elem_value *ucontrol)
0172 {
0173     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0174     struct snd_wm8776 *wm =
0175         &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
0176     unsigned int idx = kcontrol->private_value;
0177 
0178     mutex_lock(&chip->mutex);
0179     ucontrol->value.integer.value[0] = wm->volumes[idx][0];
0180     ucontrol->value.integer.value[1] = wm->volumes[idx][1];
0181     mutex_unlock(&chip->mutex);
0182     return 0;
0183 }
0184 
0185 static int maya_vol_put(struct snd_kcontrol *kcontrol,
0186             struct snd_ctl_elem_value *ucontrol)
0187 {
0188     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0189     struct snd_wm8776 *wm =
0190         &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
0191     unsigned int idx = kcontrol->private_value;
0192     const struct maya_vol_info *vol = &vol_info[idx];
0193     unsigned int val, data;
0194     int ch, changed = 0;
0195 
0196     mutex_lock(&chip->mutex);
0197     for (ch = 0; ch < 2; ch++) {
0198         val = ucontrol->value.integer.value[ch];
0199         if (val > vol->maxval)
0200             val = vol->maxval;
0201         if (val == wm->volumes[idx][ch])
0202             continue;
0203         if (!val)
0204             data = vol->mute;
0205         else
0206             data = (val - 1) + vol->offset;
0207         data |= vol->update;
0208         changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
0209                          vol->mask | vol->update, data);
0210         if (vol->mux_bits[ch])
0211             wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
0212                       vol->mux_bits[ch],
0213                       val ? 0 : vol->mux_bits[ch]);
0214         wm->volumes[idx][ch] = val;
0215     }
0216     mutex_unlock(&chip->mutex);
0217     return changed;
0218 }
0219 
0220 /*
0221  * WM8776 switch controls
0222  */
0223 
0224 #define COMPOSE_SW_VAL(idx, reg, mask)  ((idx) | ((reg) << 8) | ((mask) << 16))
0225 #define GET_SW_VAL_IDX(val) ((val) & 0xff)
0226 #define GET_SW_VAL_REG(val) (((val) >> 8) & 0xff)
0227 #define GET_SW_VAL_MASK(val)    (((val) >> 16) & 0xff)
0228 
0229 #define maya_sw_info    snd_ctl_boolean_mono_info
0230 
0231 static int maya_sw_get(struct snd_kcontrol *kcontrol,
0232                struct snd_ctl_elem_value *ucontrol)
0233 {
0234     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0235     struct snd_wm8776 *wm =
0236         &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
0237     unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
0238 
0239     ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
0240     return 0;
0241 }
0242 
0243 static int maya_sw_put(struct snd_kcontrol *kcontrol,
0244                struct snd_ctl_elem_value *ucontrol)
0245 {
0246     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0247     struct snd_wm8776 *wm =
0248         &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
0249     unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
0250     unsigned int mask, val;
0251     int changed;
0252 
0253     mutex_lock(&chip->mutex);
0254     mask = 1 << idx;
0255     wm->switch_bits &= ~mask;
0256     val = ucontrol->value.integer.value[0];
0257     if (val)
0258         wm->switch_bits |= mask;
0259     mask = GET_SW_VAL_MASK(kcontrol->private_value);
0260     changed = wm8776_write_bits(chip->ice, wm,
0261                     GET_SW_VAL_REG(kcontrol->private_value),
0262                     mask, val ? mask : 0);
0263     mutex_unlock(&chip->mutex);
0264     return changed;
0265 }
0266 
0267 /*
0268  * GPIO pins (known ones for maya44)
0269  */
0270 #define GPIO_PHANTOM_OFF    2
0271 #define GPIO_MIC_RELAY      4
0272 #define GPIO_SPDIF_IN_INV   5
0273 #define GPIO_MUST_BE_0      7
0274 
0275 /*
0276  * GPIO switch controls
0277  */
0278 
0279 #define COMPOSE_GPIO_VAL(shift, inv)    ((shift) | ((inv) << 8))
0280 #define GET_GPIO_VAL_SHIFT(val)     ((val) & 0xff)
0281 #define GET_GPIO_VAL_INV(val)       (((val) >> 8) & 1)
0282 
0283 static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
0284                   unsigned int bits)
0285 {
0286     unsigned int data;
0287     data = snd_ice1712_gpio_read(ice);
0288     if ((data & mask) == bits)
0289         return 0;
0290     snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
0291     return 1;
0292 }
0293 
0294 #define maya_gpio_sw_info   snd_ctl_boolean_mono_info
0295 
0296 static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
0297                 struct snd_ctl_elem_value *ucontrol)
0298 {
0299     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0300     unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
0301     unsigned int val;
0302 
0303     val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
0304     if (GET_GPIO_VAL_INV(kcontrol->private_value))
0305         val = !val;
0306     ucontrol->value.integer.value[0] = val;
0307     return 0;
0308 }
0309 
0310 static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
0311                 struct snd_ctl_elem_value *ucontrol)
0312 {
0313     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0314     unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
0315     unsigned int val, mask;
0316     int changed;
0317 
0318     mutex_lock(&chip->mutex);
0319     mask = 1 << shift;
0320     val = ucontrol->value.integer.value[0];
0321     if (GET_GPIO_VAL_INV(kcontrol->private_value))
0322         val = !val;
0323     val = val ? mask : 0;
0324     changed = maya_set_gpio_bits(chip->ice, mask, val);
0325     mutex_unlock(&chip->mutex);
0326     return changed;
0327 }
0328 
0329 /*
0330  * capture source selection
0331  */
0332 
0333 /* known working input slots (0-4) */
0334 #define MAYA_LINE_IN    1   /* in-2 */
0335 #define MAYA_MIC_IN 3   /* in-4 */
0336 
0337 static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
0338 {
0339     wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
0340               0x1f, 1 << line);
0341 }
0342 
0343 static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
0344                  struct snd_ctl_elem_info *uinfo)
0345 {
0346     static const char * const texts[] = { "Line", "Mic" };
0347 
0348     return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
0349 }
0350 
0351 static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
0352                 struct snd_ctl_elem_value *ucontrol)
0353 {
0354     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0355     int sel;
0356 
0357     if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
0358         sel = 1;
0359     else
0360         sel = 0;
0361     ucontrol->value.enumerated.item[0] = sel;
0362     return 0;
0363 }
0364 
0365 static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
0366                 struct snd_ctl_elem_value *ucontrol)
0367 {
0368     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0369     int sel = ucontrol->value.enumerated.item[0];
0370     int changed;
0371 
0372     mutex_lock(&chip->mutex);
0373     changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
0374                      sel ? (1 << GPIO_MIC_RELAY) : 0);
0375     wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
0376     mutex_unlock(&chip->mutex);
0377     return changed;
0378 }
0379 
0380 /*
0381  * Maya44 routing switch settings have different meanings than the standard
0382  * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
0383  */
0384 static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
0385                   struct snd_ctl_elem_info *uinfo)
0386 {
0387     static const char * const texts[] = {
0388         "PCM Out", /* 0 */
0389         "Input 1", "Input 2", "Input 3", "Input 4"
0390     };
0391 
0392     return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
0393 }
0394 
0395 static int maya_pb_route_shift(int idx)
0396 {
0397     static const unsigned char shift[10] =
0398         { 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
0399     return shift[idx % 10];
0400 }
0401 
0402 static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
0403                  struct snd_ctl_elem_value *ucontrol)
0404 {
0405     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0406     int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
0407     ucontrol->value.enumerated.item[0] =
0408         snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
0409     return 0;
0410 }
0411 
0412 static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
0413                  struct snd_ctl_elem_value *ucontrol)
0414 {
0415     struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
0416     int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
0417     return snd_ice1724_put_route_val(chip->ice,
0418                      ucontrol->value.enumerated.item[0],
0419                      maya_pb_route_shift(idx));
0420 }
0421 
0422 
0423 /*
0424  * controls to be added
0425  */
0426 
0427 static const struct snd_kcontrol_new maya_controls[] = {
0428     {
0429         .name = "Crossmix Playback Volume",
0430         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0431         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
0432             SNDRV_CTL_ELEM_ACCESS_TLV_READ,
0433         .info = maya_vol_info,
0434         .get = maya_vol_get,
0435         .put = maya_vol_put,
0436         .tlv = { .p = db_scale_hp },
0437         .private_value = WM_VOL_HP,
0438         .count = 2,
0439     },
0440     {
0441         .name = "PCM Playback Volume",
0442         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0443         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
0444             SNDRV_CTL_ELEM_ACCESS_TLV_READ,
0445         .info = maya_vol_info,
0446         .get = maya_vol_get,
0447         .put = maya_vol_put,
0448         .tlv = { .p = db_scale_dac },
0449         .private_value = WM_VOL_DAC,
0450         .count = 2,
0451     },
0452     {
0453         .name = "Line Capture Volume",
0454         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0455         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
0456             SNDRV_CTL_ELEM_ACCESS_TLV_READ,
0457         .info = maya_vol_info,
0458         .get = maya_vol_get,
0459         .put = maya_vol_put,
0460         .tlv = { .p = db_scale_adc },
0461         .private_value = WM_VOL_ADC,
0462         .count = 2,
0463     },
0464     {
0465         .name = "PCM Playback Switch",
0466         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0467         .info = maya_sw_info,
0468         .get = maya_sw_get,
0469         .put = maya_sw_put,
0470         .private_value = COMPOSE_SW_VAL(WM_SW_DAC,
0471                         WM8776_REG_OUTPUT_MUX, 0x01),
0472         .count = 2,
0473     },
0474     {
0475         .name = "Bypass Playback Switch",
0476         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0477         .info = maya_sw_info,
0478         .get = maya_sw_get,
0479         .put = maya_sw_put,
0480         .private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
0481                         WM8776_REG_OUTPUT_MUX, 0x04),
0482         .count = 2,
0483     },
0484     {
0485         .name = "Capture Source",
0486         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0487         .info = maya_rec_src_info,
0488         .get = maya_rec_src_get,
0489         .put = maya_rec_src_put,
0490     },
0491     {
0492         .name = "Mic Phantom Power Switch",
0493         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0494         .info = maya_gpio_sw_info,
0495         .get = maya_gpio_sw_get,
0496         .put = maya_gpio_sw_put,
0497         .private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
0498     },
0499     {
0500         .name = "SPDIF Capture Switch",
0501         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0502         .info = maya_gpio_sw_info,
0503         .get = maya_gpio_sw_get,
0504         .put = maya_gpio_sw_put,
0505         .private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
0506     },
0507     {
0508         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0509         .name = "H/W Playback Route",
0510         .info = maya_pb_route_info,
0511         .get = maya_pb_route_get,
0512         .put = maya_pb_route_put,
0513         .count = 4,  /* FIXME: do controls 5-9 have any meaning? */
0514     },
0515 };
0516 
0517 static int maya44_add_controls(struct snd_ice1712 *ice)
0518 {
0519     int err, i;
0520 
0521     for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
0522         err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
0523                               ice->spec));
0524         if (err < 0)
0525             return err;
0526     }
0527     return 0;
0528 }
0529 
0530 
0531 /*
0532  * initialize a wm8776 chip
0533  */
0534 static void wm8776_init(struct snd_ice1712 *ice,
0535             struct snd_wm8776 *wm, unsigned int addr)
0536 {
0537     static const unsigned short inits_wm8776[] = {
0538         0x02, 0x100, /* R2: headphone L+R muted + update */
0539         0x05, 0x100, /* R5: DAC output L+R muted + update */
0540         0x06, 0x000, /* R6: DAC output phase normal */
0541         0x07, 0x091, /* R7: DAC enable zero cross detection,
0542                 normal output */
0543         0x08, 0x000, /* R8: DAC soft mute off */
0544         0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
0545         0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
0546         0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
0547                 highpass filter enabled */
0548         0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
0549         0x0d, 0x000, /* R13: all power up */
0550         0x0e, 0x100, /* R14: ADC left muted,
0551                 enable zero cross detection */
0552         0x0f, 0x100, /* R15: ADC right muted,
0553                 enable zero cross detection */
0554                  /* R16: ALC...*/
0555         0x11, 0x000, /* R17: disable ALC */
0556                  /* R18: ALC...*/
0557                  /* R19: noise gate...*/
0558         0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
0559         0x16, 0x001, /* R22: output mux, select DAC */
0560         0xff, 0xff
0561     };
0562 
0563     const unsigned short *ptr;
0564     unsigned char reg;
0565     unsigned short data;
0566 
0567     wm->addr = addr;
0568     /* enable DAC output; mute bypass, aux & all inputs */
0569     wm->switch_bits = (1 << WM_SW_DAC);
0570 
0571     ptr = inits_wm8776;
0572     while (*ptr != 0xff) {
0573         reg = *ptr++;
0574         data = *ptr++;
0575         wm8776_write(ice, wm, reg, data);
0576     }
0577 }
0578 
0579 
0580 /*
0581  * change the rate on the WM8776 codecs.
0582  * this assumes that the VT17xx's rate is changed by the calling function.
0583  * NOTE: even though the WM8776's are running in slave mode and rate
0584  * selection is automatic, we need to call snd_wm8776_set_rate() here
0585  * to make sure some flags are set correctly.
0586  */
0587 static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
0588 {
0589     struct snd_maya44 *chip = ice->spec;
0590     unsigned int ratio, adc_ratio, val;
0591     int i;
0592 
0593     switch (rate) {
0594     case 192000:
0595         ratio = WM8776_CLOCK_RATIO_128FS;
0596         break;
0597     case 176400:
0598         ratio = WM8776_CLOCK_RATIO_128FS;
0599         break;
0600     case 96000:
0601         ratio = WM8776_CLOCK_RATIO_256FS;
0602         break;
0603     case 88200:
0604         ratio = WM8776_CLOCK_RATIO_384FS;
0605         break;
0606     case 48000:
0607         ratio = WM8776_CLOCK_RATIO_512FS;
0608         break;
0609     case 44100:
0610         ratio = WM8776_CLOCK_RATIO_512FS;
0611         break;
0612     case 32000:
0613         ratio = WM8776_CLOCK_RATIO_768FS;
0614         break;
0615     case 0:
0616         /* no hint - S/PDIF input is master, simply return */
0617         return;
0618     default:
0619         snd_BUG();
0620         return;
0621     }
0622 
0623     /*
0624      * this currently sets the same rate for ADC and DAC, but limits
0625      * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
0626      * oversampling to 64x, as recommended by WM8776 datasheet.
0627      * Setting the rate is not really necessary in slave mode.
0628      */
0629     adc_ratio = ratio;
0630     if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
0631         adc_ratio = WM8776_CLOCK_RATIO_256FS;
0632 
0633     val = adc_ratio;
0634     if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
0635         val |= 8;
0636     val |= ratio << 4;
0637 
0638     mutex_lock(&chip->mutex);
0639     for (i = 0; i < 2; i++)
0640         wm8776_write_bits(ice, &chip->wm[i],
0641                   WM8776_REG_MASTER_MODE_CONTROL,
0642                   0x180, val);
0643     mutex_unlock(&chip->mutex);
0644 }
0645 
0646 /*
0647  * supported sample rates (to override the default one)
0648  */
0649 
0650 static const unsigned int rates[] = {
0651     32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
0652 };
0653 
0654 /* playback rates: 32..192 kHz */
0655 static const struct snd_pcm_hw_constraint_list dac_rates = {
0656     .count = ARRAY_SIZE(rates),
0657     .list = rates,
0658     .mask = 0
0659 };
0660 
0661 
0662 /*
0663  * chip addresses on I2C bus
0664  */
0665 static const unsigned char wm8776_addr[2] = {
0666     0x34, 0x36, /* codec 0 & 1 */
0667 };
0668 
0669 /*
0670  * initialize the chip
0671  */
0672 static int maya44_init(struct snd_ice1712 *ice)
0673 {
0674     int i;
0675     struct snd_maya44 *chip;
0676 
0677     chip = kzalloc(sizeof(*chip), GFP_KERNEL);
0678     if (!chip)
0679         return -ENOMEM;
0680     mutex_init(&chip->mutex);
0681     chip->ice = ice;
0682     ice->spec = chip;
0683 
0684     /* initialise codecs */
0685     ice->num_total_dacs = 4;
0686     ice->num_total_adcs = 4;
0687     ice->akm_codecs = 0;
0688 
0689     for (i = 0; i < 2; i++) {
0690         wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
0691         wm8776_select_input(chip, i, MAYA_LINE_IN);
0692     }
0693 
0694     /* set card specific rates */
0695     ice->hw_rates = &dac_rates;
0696 
0697     /* register change rate notifier */
0698     ice->gpio.set_pro_rate = set_rate;
0699 
0700     /* RDMA1 (2nd input channel) is used for ADC by default */
0701     ice->force_rdma1 = 1;
0702 
0703     /* have an own routing control */
0704     ice->own_routing = 1;
0705 
0706     return 0;
0707 }
0708 
0709 
0710 /*
0711  * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
0712  * hence the driver needs to sets up it properly.
0713  */
0714 
0715 static const unsigned char maya44_eeprom[] = {
0716     [ICE_EEP2_SYSCONF]     = 0x45,
0717         /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
0718     [ICE_EEP2_ACLINK]      = 0x80,
0719         /* I2S */
0720     [ICE_EEP2_I2S]         = 0xf8,
0721         /* vol, 96k, 24bit, 192k */
0722     [ICE_EEP2_SPDIF]       = 0xc3,
0723         /* enable spdif out, spdif out supp, spdif-in, ext spdif out */
0724     [ICE_EEP2_GPIO_DIR]    = 0xff,
0725     [ICE_EEP2_GPIO_DIR1]   = 0xff,
0726     [ICE_EEP2_GPIO_DIR2]   = 0xff,
0727     [ICE_EEP2_GPIO_MASK]   = 0/*0x9f*/,
0728     [ICE_EEP2_GPIO_MASK1]  = 0/*0xff*/,
0729     [ICE_EEP2_GPIO_MASK2]  = 0/*0x7f*/,
0730     [ICE_EEP2_GPIO_STATE]  = (1 << GPIO_PHANTOM_OFF) |
0731             (1 << GPIO_SPDIF_IN_INV),
0732     [ICE_EEP2_GPIO_STATE1] = 0x00,
0733     [ICE_EEP2_GPIO_STATE2] = 0x00,
0734 };
0735 
0736 /* entry point */
0737 struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
0738     {
0739         .subvendor = VT1724_SUBDEVICE_MAYA44,
0740         .name = "ESI Maya44",
0741         .model = "maya44",
0742         .chip_init = maya44_init,
0743         .build_controls = maya44_add_controls,
0744         .eeprom_size = sizeof(maya44_eeprom),
0745         .eeprom_data = maya44_eeprom,
0746     },
0747     { } /* terminator */
0748 };