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        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 363        uinfo->count = 1;
 364        uinfo->value.enumerated.items = ARRAY_SIZE(texts);
 365        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 366                uinfo->value.enumerated.item =
 367                        uinfo->value.enumerated.items - 1;
 368        strcpy(uinfo->value.enumerated.name,
 369               texts[uinfo->value.enumerated.item]);
 370        return 0;
 371}
 372
 373static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
 374                            struct snd_ctl_elem_value *ucontrol)
 375{
 376        struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
 377        int sel;
 378
 379        if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
 380                sel = 1;
 381        else
 382                sel = 0;
 383        ucontrol->value.enumerated.item[0] = sel;
 384        return 0;
 385}
 386
 387static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
 388                            struct snd_ctl_elem_value *ucontrol)
 389{
 390        struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
 391        int sel = ucontrol->value.enumerated.item[0];
 392        int changed;
 393
 394        mutex_lock(&chip->mutex);
 395        changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
 396                                     sel ? (1 << GPIO_MIC_RELAY) : 0);
 397        wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
 398        mutex_unlock(&chip->mutex);
 399        return changed;
 400}
 401
 402/*
 403 * Maya44 routing switch settings have different meanings than the standard
 404 * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
 405 */
 406static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
 407                              struct snd_ctl_elem_info *uinfo)
 408{
 409        static const char * const texts[] = {
 410                "PCM Out", /* 0 */
 411                "Input 1", "Input 2", "Input 3", "Input 4"
 412        };
 413
 414        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 415        uinfo->count = 1;
 416        uinfo->value.enumerated.items = ARRAY_SIZE(texts);
 417        if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 418                uinfo->value.enumerated.item =
 419                        uinfo->value.enumerated.items - 1;
 420        strcpy(uinfo->value.enumerated.name,
 421               texts[uinfo->value.enumerated.item]);
 422        return 0;
 423}
 424
 425static int maya_pb_route_shift(int idx)
 426{
 427        static const unsigned char shift[10] =
 428                { 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
 429        return shift[idx % 10];
 430}
 431
 432static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
 433                             struct snd_ctl_elem_value *ucontrol)
 434{
 435        struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
 436        int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 437        ucontrol->value.enumerated.item[0] =
 438                snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
 439        return 0;
 440}
 441
 442static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
 443                             struct snd_ctl_elem_value *ucontrol)
 444{
 445        struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
 446        int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 447        return snd_ice1724_put_route_val(chip->ice,
 448                                         ucontrol->value.enumerated.item[0],
 449                                         maya_pb_route_shift(idx));
 450}
 451
 452
 453/*
 454 * controls to be added
 455 */
 456
 457static struct snd_kcontrol_new maya_controls[] = {
 458        {
 459                .name = "Crossmix Playback Volume",
 460                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 461                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 462                        SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 463                .info = maya_vol_info,
 464                .get = maya_vol_get,
 465                .put = maya_vol_put,
 466                .tlv = { .p = db_scale_hp },
 467                .private_value = WM_VOL_HP,
 468                .count = 2,
 469        },
 470        {
 471                .name = "PCM Playback Volume",
 472                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 473                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 474                        SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 475                .info = maya_vol_info,
 476                .get = maya_vol_get,
 477                .put = maya_vol_put,
 478                .tlv = { .p = db_scale_dac },
 479                .private_value = WM_VOL_DAC,
 480                .count = 2,
 481        },
 482        {
 483                .name = "Line Capture Volume",
 484                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 485                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 486                        SNDRV_CTL_ELEM_ACCESS_TLV_READ,
 487                .info = maya_vol_info,
 488                .get = maya_vol_get,
 489                .put = maya_vol_put,
 490                .tlv = { .p = db_scale_adc },
 491                .private_value = WM_VOL_ADC,
 492                .count = 2,
 493        },
 494        {
 495                .name = "PCM Playback Switch",
 496                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 497                .info = maya_sw_info,
 498                .get = maya_sw_get,
 499                .put = maya_sw_put,
 500                .private_value = COMPOSE_SW_VAL(WM_SW_DAC,
 501                                                WM8776_REG_OUTPUT_MUX, 0x01),
 502                .count = 2,
 503        },
 504        {
 505                .name = "Bypass Playback Switch",
 506                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 507                .info = maya_sw_info,
 508                .get = maya_sw_get,
 509                .put = maya_sw_put,
 510                .private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
 511                                                WM8776_REG_OUTPUT_MUX, 0x04),
 512                .count = 2,
 513        },
 514        {
 515                .name = "Capture Source",
 516                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 517                .info = maya_rec_src_info,
 518                .get = maya_rec_src_get,
 519                .put = maya_rec_src_put,
 520        },
 521        {
 522                .name = "Mic Phantom Power Switch",
 523                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 524                .info = maya_gpio_sw_info,
 525                .get = maya_gpio_sw_get,
 526                .put = maya_gpio_sw_put,
 527                .private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
 528        },
 529        {
 530                .name = "SPDIF Capture Switch",
 531                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 532                .info = maya_gpio_sw_info,
 533                .get = maya_gpio_sw_get,
 534                .put = maya_gpio_sw_put,
 535                .private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
 536        },
 537        {
 538                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 539                .name = "H/W Playback Route",
 540                .info = maya_pb_route_info,
 541                .get = maya_pb_route_get,
 542                .put = maya_pb_route_put,
 543                .count = 4,  /* FIXME: do controls 5-9 have any meaning? */
 544        },
 545};
 546
 547static int maya44_add_controls(struct snd_ice1712 *ice)
 548{
 549        int err, i;
 550
 551        for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
 552                err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
 553                                                          ice->spec));
 554                if (err < 0)
 555                        return err;
 556        }
 557        return 0;
 558}
 559
 560
 561/*
 562 * initialize a wm8776 chip
 563 */
 564static void wm8776_init(struct snd_ice1712 *ice,
 565                        struct snd_wm8776 *wm, unsigned int addr)
 566{
 567        static const unsigned short inits_wm8776[] = {
 568                0x02, 0x100, /* R2: headphone L+R muted + update */
 569                0x05, 0x100, /* R5: DAC output L+R muted + update */
 570                0x06, 0x000, /* R6: DAC output phase normal */
 571                0x07, 0x091, /* R7: DAC enable zero cross detection,
 572                                normal output */
 573                0x08, 0x000, /* R8: DAC soft mute off */
 574                0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
 575                0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
 576                0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
 577                                highpass filter enabled */
 578                0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
 579                0x0d, 0x000, /* R13: all power up */
 580                0x0e, 0x100, /* R14: ADC left muted,
 581                                enable zero cross detection */
 582                0x0f, 0x100, /* R15: ADC right muted,
 583                                enable zero cross detection */
 584                             /* R16: ALC...*/
 585                0x11, 0x000, /* R17: disable ALC */
 586                             /* R18: ALC...*/
 587                             /* R19: noise gate...*/
 588                0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
 589                0x16, 0x001, /* R22: output mux, select DAC */
 590                0xff, 0xff
 591        };
 592
 593        const unsigned short *ptr;
 594        unsigned char reg;
 595        unsigned short data;
 596
 597        wm->addr = addr;
 598        /* enable DAC output; mute bypass, aux & all inputs */
 599        wm->switch_bits = (1 << WM_SW_DAC);
 600
 601        ptr = inits_wm8776;
 602        while (*ptr != 0xff) {
 603                reg = *ptr++;
 604                data = *ptr++;
 605                wm8776_write(ice, wm, reg, data);
 606        }
 607}
 608
 609
 610/*
 611 * change the rate on the WM8776 codecs.
 612 * this assumes that the VT17xx's rate is changed by the calling function.
 613 * NOTE: even though the WM8776's are running in slave mode and rate
 614 * selection is automatic, we need to call snd_wm8776_set_rate() here
 615 * to make sure some flags are set correctly.
 616 */
 617static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
 618{
 619        struct snd_maya44 *chip = ice->spec;
 620        unsigned int ratio, adc_ratio, val;
 621        int i;
 622
 623        switch (rate) {
 624        case 192000:
 625                ratio = WM8776_CLOCK_RATIO_128FS;
 626                break;
 627        case 176400:
 628                ratio = WM8776_CLOCK_RATIO_128FS;
 629                break;
 630        case 96000:
 631                ratio = WM8776_CLOCK_RATIO_256FS;
 632                break;
 633        case 88200:
 634                ratio = WM8776_CLOCK_RATIO_384FS;
 635                break;
 636        case 48000:
 637                ratio = WM8776_CLOCK_RATIO_512FS;
 638                break;
 639        case 44100:
 640                ratio = WM8776_CLOCK_RATIO_512FS;
 641                break;
 642        case 32000:
 643                ratio = WM8776_CLOCK_RATIO_768FS;
 644                break;
 645        case 0:
 646                /* no hint - S/PDIF input is master, simply return */
 647                return;
 648        default:
 649                snd_BUG();
 650                return;
 651        }
 652
 653        /*
 654         * this currently sets the same rate for ADC and DAC, but limits
 655         * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
 656         * oversampling to 64x, as recommended by WM8776 datasheet.
 657         * Setting the rate is not really necessary in slave mode.
 658         */
 659        adc_ratio = ratio;
 660        if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
 661                adc_ratio = WM8776_CLOCK_RATIO_256FS;
 662
 663        val = adc_ratio;
 664        if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
 665                val |= 8;
 666        val |= ratio << 4;
 667
 668        mutex_lock(&chip->mutex);
 669        for (i = 0; i < 2; i++)
 670                wm8776_write_bits(ice, &chip->wm[i],
 671                                  WM8776_REG_MASTER_MODE_CONTROL,
 672                                  0x180, val);
 673        mutex_unlock(&chip->mutex);
 674}
 675
 676/*
 677 * supported sample rates (to override the default one)
 678 */
 679
 680static unsigned int rates[] = {
 681        32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
 682};
 683
 684/* playback rates: 32..192 kHz */
 685static struct snd_pcm_hw_constraint_list dac_rates = {
 686        .count = ARRAY_SIZE(rates),
 687        .list = rates,
 688        .mask = 0
 689};
 690
 691
 692/*
 693 * chip addresses on I2C bus
 694 */
 695static unsigned char wm8776_addr[2] = {
 696        0x34, 0x36, /* codec 0 & 1 */
 697};
 698
 699/*
 700 * initialize the chip
 701 */
 702static int maya44_init(struct snd_ice1712 *ice)
 703{
 704        int i;
 705        struct snd_maya44 *chip;
 706
 707        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 708        if (!chip)
 709                return -ENOMEM;
 710        mutex_init(&chip->mutex);
 711        chip->ice = ice;
 712        ice->spec = chip;
 713
 714        /* initialise codecs */
 715        ice->num_total_dacs = 4;
 716        ice->num_total_adcs = 4;
 717        ice->akm_codecs = 0;
 718
 719        for (i = 0; i < 2; i++) {
 720                wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
 721                wm8776_select_input(chip, i, MAYA_LINE_IN);
 722        }
 723
 724        /* set card specific rates */
 725        ice->hw_rates = &dac_rates;
 726
 727        /* register change rate notifier */
 728        ice->gpio.set_pro_rate = set_rate;
 729
 730        /* RDMA1 (2nd input channel) is used for ADC by default */
 731        ice->force_rdma1 = 1;
 732
 733        /* have an own routing control */
 734        ice->own_routing = 1;
 735
 736        return 0;
 737}
 738
 739
 740/*
 741 * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
 742 * hence the driver needs to sets up it properly.
 743 */
 744
 745static unsigned char maya44_eeprom[] = {
 746        [ICE_EEP2_SYSCONF]     = 0x45,
 747                /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
 748        [ICE_EEP2_ACLINK]      = 0x80,
 749                /* I2S */
 750        [ICE_EEP2_I2S]         = 0xf8,
 751                /* vol, 96k, 24bit, 192k */
 752        [ICE_EEP2_SPDIF]       = 0xc3,
 753                /* enable spdif out, spdif out supp, spdif-in, ext spdif out */
 754        [ICE_EEP2_GPIO_DIR]    = 0xff,
 755        [ICE_EEP2_GPIO_DIR1]   = 0xff,
 756        [ICE_EEP2_GPIO_DIR2]   = 0xff,
 757        [ICE_EEP2_GPIO_MASK]   = 0/*0x9f*/,
 758        [ICE_EEP2_GPIO_MASK1]  = 0/*0xff*/,
 759        [ICE_EEP2_GPIO_MASK2]  = 0/*0x7f*/,
 760        [ICE_EEP2_GPIO_STATE]  = (1 << GPIO_PHANTOM_OFF) |
 761                        (1 << GPIO_SPDIF_IN_INV),
 762        [ICE_EEP2_GPIO_STATE1] = 0x00,
 763        [ICE_EEP2_GPIO_STATE2] = 0x00,
 764};
 765
 766/* entry point */
 767struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
 768        {
 769                .subvendor = VT1724_SUBDEVICE_MAYA44,
 770                .name = "ESI Maya44",
 771                .model = "maya44",
 772                .chip_init = maya44_init,
 773                .build_controls = maya44_add_controls,
 774                .eeprom_size = sizeof(maya44_eeprom),
 775                .eeprom_data = maya44_eeprom,
 776        },
 777        { } /* terminator */
 778};
 779