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