linux/sound/pci/ice1712/phase.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *   ALSA driver for ICEnsemble ICE1724 (Envy24)
   4 *
   5 *   Lowlevel functions for Terratec PHASE 22
   6 *
   7 *      Copyright (c) 2005 Misha Zhilin <misha@epiphan.com>
   8 */
   9
  10/* PHASE 22 overview:
  11 *   Audio controller: VIA Envy24HT-S (slightly trimmed down Envy24HT, 4in/4out)
  12 *   Analog chip: AK4524 (partially via Philip's 74HCT125)
  13 *   Digital receiver: CS8414-CS (supported in this release)
  14 *              PHASE 22 revision 2.0 and Terrasoniq/Musonik TS22PCI have CS8416
  15 *              (support status unknown, please test and report)
  16 *
  17 *   Envy connects to AK4524
  18 *      - CS directly from GPIO 10
  19 *      - CCLK via 74HCT125's gate #4 from GPIO 4
  20 *      - CDTI via 74HCT125's gate #2 from GPIO 5
  21 *              CDTI may be completely blocked by 74HCT125's gate #1
  22 *              controlled by GPIO 3
  23 */
  24
  25/* PHASE 28 overview:
  26 *   Audio controller: VIA Envy24HT (full untrimmed version, 4in/8out)
  27 *   Analog chip: WM8770 (8 channel 192k DAC, 2 channel 96k ADC)
  28 *   Digital receiver: CS8414-CS (supported in this release)
  29 */
  30
  31#include <linux/delay.h>
  32#include <linux/interrupt.h>
  33#include <linux/init.h>
  34#include <linux/slab.h>
  35#include <linux/mutex.h>
  36
  37#include <sound/core.h>
  38
  39#include "ice1712.h"
  40#include "envy24ht.h"
  41#include "phase.h"
  42#include <sound/tlv.h>
  43
  44/* AC97 register cache for Phase28 */
  45struct phase28_spec {
  46        unsigned short master[2];
  47        unsigned short vol[8];
  48};
  49
  50/* WM8770 registers */
  51#define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
  52#define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
  53#define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
  54#define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
  55#define WM_PHASE_SWAP           0x12    /* DAC phase */
  56#define WM_DAC_CTRL1            0x13    /* DAC control bits */
  57#define WM_MUTE                 0x14    /* mute controls */
  58#define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
  59#define WM_INT_CTRL             0x16    /* interface control */
  60#define WM_MASTER               0x17    /* master clock and mode */
  61#define WM_POWERDOWN            0x18    /* power-down controls */
  62#define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
  63#define WM_ADC_MUX              0x1b    /* input MUX */
  64#define WM_OUT_MUX1             0x1c    /* output MUX */
  65#define WM_OUT_MUX2             0x1e    /* output MUX */
  66#define WM_RESET                0x1f    /* software reset */
  67
  68
  69/*
  70 * Logarithmic volume values for WM8770
  71 * Computed as 20 * Log10(255 / x)
  72 */
  73static const unsigned char wm_vol[256] = {
  74        127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24,
  75        24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18,
  76        17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14,
  77        14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
  78        11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9,
  79        9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
  80        7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
  81        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  82        4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  83        3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  84        2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  85        1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  86};
  87
  88#define WM_VOL_MAX      (sizeof(wm_vol) - 1)
  89#define WM_VOL_MUTE     0x8000
  90
  91static const struct snd_akm4xxx akm_phase22 = {
  92        .type = SND_AK4524,
  93        .num_dacs = 2,
  94        .num_adcs = 2,
  95};
  96
  97static const struct snd_ak4xxx_private akm_phase22_priv = {
  98        .caddr =        2,
  99        .cif =          1,
 100        .data_mask =    1 << 4,
 101        .clk_mask =     1 << 5,
 102        .cs_mask =      1 << 10,
 103        .cs_addr =      1 << 10,
 104        .cs_none =      0,
 105        .add_flags =    1 << 3,
 106        .mask_flags =   0,
 107};
 108
 109static int phase22_init(struct snd_ice1712 *ice)
 110{
 111        struct snd_akm4xxx *ak;
 112        int err;
 113
 114        /* Configure DAC/ADC description for generic part of ice1724 */
 115        switch (ice->eeprom.subvendor) {
 116        case VT1724_SUBDEVICE_PHASE22:
 117        case VT1724_SUBDEVICE_TS22:
 118                ice->num_total_dacs = 2;
 119                ice->num_total_adcs = 2;
 120                ice->vt1720 = 1; /* Envy24HT-S have 16 bit wide GPIO */
 121                break;
 122        default:
 123                snd_BUG();
 124                return -EINVAL;
 125        }
 126
 127        /* Initialize analog chips */
 128        ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
 129        ak = ice->akm;
 130        if (!ak)
 131                return -ENOMEM;
 132        ice->akm_codecs = 1;
 133        switch (ice->eeprom.subvendor) {
 134        case VT1724_SUBDEVICE_PHASE22:
 135        case VT1724_SUBDEVICE_TS22:
 136                err = snd_ice1712_akm4xxx_init(ak, &akm_phase22,
 137                                                &akm_phase22_priv, ice);
 138                if (err < 0)
 139                        return err;
 140                break;
 141        }
 142
 143        return 0;
 144}
 145
 146static int phase22_add_controls(struct snd_ice1712 *ice)
 147{
 148        int err = 0;
 149
 150        switch (ice->eeprom.subvendor) {
 151        case VT1724_SUBDEVICE_PHASE22:
 152        case VT1724_SUBDEVICE_TS22:
 153                err = snd_ice1712_akm4xxx_build_controls(ice);
 154                if (err < 0)
 155                        return err;
 156        }
 157        return 0;
 158}
 159
 160static const unsigned char phase22_eeprom[] = {
 161        [ICE_EEP2_SYSCONF]     = 0x28,  /* clock 512, mpu 401,
 162                                        spdif-in/1xADC, 1xDACs */
 163        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
 164        [ICE_EEP2_I2S]         = 0xf0,  /* vol, 96k, 24bit */
 165        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
 166        [ICE_EEP2_GPIO_DIR]    = 0xff,
 167        [ICE_EEP2_GPIO_DIR1]   = 0xff,
 168        [ICE_EEP2_GPIO_DIR2]   = 0xff,
 169        [ICE_EEP2_GPIO_MASK]   = 0x00,
 170        [ICE_EEP2_GPIO_MASK1]  = 0x00,
 171        [ICE_EEP2_GPIO_MASK2]  = 0x00,
 172        [ICE_EEP2_GPIO_STATE]  = 0x00,
 173        [ICE_EEP2_GPIO_STATE1] = 0x00,
 174        [ICE_EEP2_GPIO_STATE2] = 0x00,
 175};
 176
 177static const unsigned char phase28_eeprom[] = {
 178        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401,
 179                                        spdif-in/1xADC, 4xDACs */
 180        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
 181        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
 182        [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
 183        [ICE_EEP2_GPIO_DIR]    = 0xff,
 184        [ICE_EEP2_GPIO_DIR1]   = 0xff,
 185        [ICE_EEP2_GPIO_DIR2]   = 0x5f,
 186        [ICE_EEP2_GPIO_MASK]   = 0x00,
 187        [ICE_EEP2_GPIO_MASK1]  = 0x00,
 188        [ICE_EEP2_GPIO_MASK2]  = 0x00,
 189        [ICE_EEP2_GPIO_STATE]  = 0x00,
 190        [ICE_EEP2_GPIO_STATE1] = 0x00,
 191        [ICE_EEP2_GPIO_STATE2] = 0x00,
 192};
 193
 194/*
 195 * write data in the SPI mode
 196 */
 197static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs,
 198                                unsigned int data, int bits)
 199{
 200        unsigned int tmp;
 201        int i;
 202
 203        tmp = snd_ice1712_gpio_read(ice);
 204
 205        snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|
 206                                        PHASE28_SPI_CLK|PHASE28_WM_CS));
 207        tmp |= PHASE28_WM_RW;
 208        tmp &= ~cs;
 209        snd_ice1712_gpio_write(ice, tmp);
 210        udelay(1);
 211
 212        for (i = bits - 1; i >= 0; i--) {
 213                tmp &= ~PHASE28_SPI_CLK;
 214                snd_ice1712_gpio_write(ice, tmp);
 215                udelay(1);
 216                if (data & (1 << i))
 217                        tmp |= PHASE28_SPI_MOSI;
 218                else
 219                        tmp &= ~PHASE28_SPI_MOSI;
 220                snd_ice1712_gpio_write(ice, tmp);
 221                udelay(1);
 222                tmp |= PHASE28_SPI_CLK;
 223                snd_ice1712_gpio_write(ice, tmp);
 224                udelay(1);
 225        }
 226
 227        tmp &= ~PHASE28_SPI_CLK;
 228        tmp |= cs;
 229        snd_ice1712_gpio_write(ice, tmp);
 230        udelay(1);
 231        tmp |= PHASE28_SPI_CLK;
 232        snd_ice1712_gpio_write(ice, tmp);
 233        udelay(1);
 234}
 235
 236/*
 237 * get the current register value of WM codec
 238 */
 239static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
 240{
 241        reg <<= 1;
 242        return ((unsigned short)ice->akm[0].images[reg] << 8) |
 243                ice->akm[0].images[reg + 1];
 244}
 245
 246/*
 247 * set the register value of WM codec
 248 */
 249static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
 250{
 251        phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
 252}
 253
 254/*
 255 * set the register value of WM codec and remember it
 256 */
 257static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
 258{
 259        wm_put_nocache(ice, reg, val);
 260        reg <<= 1;
 261        ice->akm[0].images[reg] = val >> 8;
 262        ice->akm[0].images[reg + 1] = val;
 263}
 264
 265static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
 266                        unsigned short vol, unsigned short master)
 267{
 268        unsigned char nvol;
 269
 270        if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
 271                nvol = 0;
 272        else
 273                nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) *
 274                        (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
 275
 276        wm_put(ice, index, nvol);
 277        wm_put_nocache(ice, index, 0x180 | nvol);
 278}
 279
 280/*
 281 * DAC mute control
 282 */
 283#define wm_pcm_mute_info        snd_ctl_boolean_mono_info
 284
 285static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol,
 286                                struct snd_ctl_elem_value *ucontrol)
 287{
 288        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 289
 290        mutex_lock(&ice->gpio_mutex);
 291        ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ?
 292                                                0 : 1;
 293        mutex_unlock(&ice->gpio_mutex);
 294        return 0;
 295}
 296
 297static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol,
 298                                struct snd_ctl_elem_value *ucontrol)
 299{
 300        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 301        unsigned short nval, oval;
 302        int change;
 303
 304        snd_ice1712_save_gpio_status(ice);
 305        oval = wm_get(ice, WM_MUTE);
 306        nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
 307        change = (nval != oval);
 308        if (change)
 309                wm_put(ice, WM_MUTE, nval);
 310        snd_ice1712_restore_gpio_status(ice);
 311
 312        return change;
 313}
 314
 315/*
 316 * Master volume attenuation mixer control
 317 */
 318static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
 319                                struct snd_ctl_elem_info *uinfo)
 320{
 321        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 322        uinfo->count = 2;
 323        uinfo->value.integer.min = 0;
 324        uinfo->value.integer.max = WM_VOL_MAX;
 325        return 0;
 326}
 327
 328static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
 329                                struct snd_ctl_elem_value *ucontrol)
 330{
 331        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 332        struct phase28_spec *spec = ice->spec;
 333        int i;
 334        for (i = 0; i < 2; i++)
 335                ucontrol->value.integer.value[i] = spec->master[i] &
 336                                                        ~WM_VOL_MUTE;
 337        return 0;
 338}
 339
 340static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
 341                                struct snd_ctl_elem_value *ucontrol)
 342{
 343        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 344        struct phase28_spec *spec = ice->spec;
 345        int ch, change = 0;
 346
 347        snd_ice1712_save_gpio_status(ice);
 348        for (ch = 0; ch < 2; ch++) {
 349                unsigned int vol = ucontrol->value.integer.value[ch];
 350                if (vol > WM_VOL_MAX)
 351                        continue;
 352                vol |= spec->master[ch] & WM_VOL_MUTE;
 353                if (vol != spec->master[ch]) {
 354                        int dac;
 355                        spec->master[ch] = vol;
 356                        for (dac = 0; dac < ice->num_total_dacs; dac += 2)
 357                                wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
 358                                           spec->vol[dac + ch],
 359                                           spec->master[ch]);
 360                        change = 1;
 361                }
 362        }
 363        snd_ice1712_restore_gpio_status(ice);
 364        return change;
 365}
 366
 367static int phase28_init(struct snd_ice1712 *ice)
 368{
 369        static const unsigned short wm_inits_phase28[] = {
 370                /* These come first to reduce init pop noise */
 371                0x1b, 0x044,    /* ADC Mux (AC'97 source) */
 372                0x1c, 0x00B,    /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
 373                0x1d, 0x009,    /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
 374
 375                0x18, 0x000,    /* All power-up */
 376
 377                0x16, 0x122,    /* I2S, normal polarity, 24bit */
 378                0x17, 0x022,    /* 256fs, slave mode */
 379                0x00, 0,        /* DAC1 analog mute */
 380                0x01, 0,        /* DAC2 analog mute */
 381                0x02, 0,        /* DAC3 analog mute */
 382                0x03, 0,        /* DAC4 analog mute */
 383                0x04, 0,        /* DAC5 analog mute */
 384                0x05, 0,        /* DAC6 analog mute */
 385                0x06, 0,        /* DAC7 analog mute */
 386                0x07, 0,        /* DAC8 analog mute */
 387                0x08, 0x100,    /* master analog mute */
 388                0x09, 0xff,     /* DAC1 digital full */
 389                0x0a, 0xff,     /* DAC2 digital full */
 390                0x0b, 0xff,     /* DAC3 digital full */
 391                0x0c, 0xff,     /* DAC4 digital full */
 392                0x0d, 0xff,     /* DAC5 digital full */
 393                0x0e, 0xff,     /* DAC6 digital full */
 394                0x0f, 0xff,     /* DAC7 digital full */
 395                0x10, 0xff,     /* DAC8 digital full */
 396                0x11, 0x1ff,    /* master digital full */
 397                0x12, 0x000,    /* phase normal */
 398                0x13, 0x090,    /* unmute DAC L/R */
 399                0x14, 0x000,    /* all unmute */
 400                0x15, 0x000,    /* no deemphasis, no ZFLG */
 401                0x19, 0x000,    /* -12dB ADC/L */
 402                0x1a, 0x000,    /* -12dB ADC/R */
 403                (unsigned short)-1
 404        };
 405
 406        unsigned int tmp;
 407        struct snd_akm4xxx *ak;
 408        struct phase28_spec *spec;
 409        const unsigned short *p;
 410        int i;
 411
 412        ice->num_total_dacs = 8;
 413        ice->num_total_adcs = 2;
 414
 415        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 416        if (!spec)
 417                return -ENOMEM;
 418        ice->spec = spec;
 419
 420        /* Initialize analog chips */
 421        ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
 422        ak = ice->akm;
 423        if (!ak)
 424                return -ENOMEM;
 425        ice->akm_codecs = 1;
 426
 427        snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */
 428
 429        /* reset the wm codec as the SPI mode */
 430        snd_ice1712_save_gpio_status(ice);
 431        snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|
 432                                        PHASE28_HP_SEL));
 433
 434        tmp = snd_ice1712_gpio_read(ice);
 435        tmp &= ~PHASE28_WM_RESET;
 436        snd_ice1712_gpio_write(ice, tmp);
 437        udelay(1);
 438        tmp |= PHASE28_WM_CS;
 439        snd_ice1712_gpio_write(ice, tmp);
 440        udelay(1);
 441        tmp |= PHASE28_WM_RESET;
 442        snd_ice1712_gpio_write(ice, tmp);
 443        udelay(1);
 444
 445        p = wm_inits_phase28;
 446        for (; *p != (unsigned short)-1; p += 2)
 447                wm_put(ice, p[0], p[1]);
 448
 449        snd_ice1712_restore_gpio_status(ice);
 450
 451        spec->master[0] = WM_VOL_MUTE;
 452        spec->master[1] = WM_VOL_MUTE;
 453        for (i = 0; i < ice->num_total_dacs; i++) {
 454                spec->vol[i] = WM_VOL_MUTE;
 455                wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
 456        }
 457
 458        return 0;
 459}
 460
 461/*
 462 * DAC volume attenuation mixer control
 463 */
 464static int wm_vol_info(struct snd_kcontrol *kcontrol,
 465                        struct snd_ctl_elem_info *uinfo)
 466{
 467        int voices = kcontrol->private_value >> 8;
 468        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 469        uinfo->count = voices;
 470        uinfo->value.integer.min = 0;           /* mute (-101dB) */
 471        uinfo->value.integer.max = 0x7F;        /* 0dB */
 472        return 0;
 473}
 474
 475static int wm_vol_get(struct snd_kcontrol *kcontrol,
 476                        struct snd_ctl_elem_value *ucontrol)
 477{
 478        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 479        struct phase28_spec *spec = ice->spec;
 480        int i, ofs, voices;
 481
 482        voices = kcontrol->private_value >> 8;
 483        ofs = kcontrol->private_value & 0xff;
 484        for (i = 0; i < voices; i++)
 485                ucontrol->value.integer.value[i] =
 486                        spec->vol[ofs+i] & ~WM_VOL_MUTE;
 487        return 0;
 488}
 489
 490static int wm_vol_put(struct snd_kcontrol *kcontrol,
 491                        struct snd_ctl_elem_value *ucontrol)
 492{
 493        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 494        struct phase28_spec *spec = ice->spec;
 495        int i, idx, ofs, voices;
 496        int change = 0;
 497
 498        voices = kcontrol->private_value >> 8;
 499        ofs = kcontrol->private_value & 0xff;
 500        snd_ice1712_save_gpio_status(ice);
 501        for (i = 0; i < voices; i++) {
 502                unsigned int vol;
 503                vol = ucontrol->value.integer.value[i];
 504                if (vol > 0x7f)
 505                        continue;
 506                vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
 507                if (vol != spec->vol[ofs+i]) {
 508                        spec->vol[ofs+i] = vol;
 509                        idx  = WM_DAC_ATTEN + ofs + i;
 510                        wm_set_vol(ice, idx, spec->vol[ofs+i],
 511                                   spec->master[i]);
 512                        change = 1;
 513                }
 514        }
 515        snd_ice1712_restore_gpio_status(ice);
 516        return change;
 517}
 518
 519/*
 520 * WM8770 mute control
 521 */
 522static int wm_mute_info(struct snd_kcontrol *kcontrol,
 523                        struct snd_ctl_elem_info *uinfo) {
 524        uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 525        uinfo->count = kcontrol->private_value >> 8;
 526        uinfo->value.integer.min = 0;
 527        uinfo->value.integer.max = 1;
 528        return 0;
 529}
 530
 531static int wm_mute_get(struct snd_kcontrol *kcontrol,
 532                        struct snd_ctl_elem_value *ucontrol)
 533{
 534        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 535        struct phase28_spec *spec = ice->spec;
 536        int voices, ofs, i;
 537
 538        voices = kcontrol->private_value >> 8;
 539        ofs = kcontrol->private_value & 0xFF;
 540
 541        for (i = 0; i < voices; i++)
 542                ucontrol->value.integer.value[i] =
 543                        (spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
 544        return 0;
 545}
 546
 547static int wm_mute_put(struct snd_kcontrol *kcontrol,
 548                        struct snd_ctl_elem_value *ucontrol)
 549{
 550        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 551        struct phase28_spec *spec = ice->spec;
 552        int change = 0, voices, ofs, i;
 553
 554        voices = kcontrol->private_value >> 8;
 555        ofs = kcontrol->private_value & 0xFF;
 556
 557        snd_ice1712_save_gpio_status(ice);
 558        for (i = 0; i < voices; i++) {
 559                int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
 560                if (ucontrol->value.integer.value[i] != val) {
 561                        spec->vol[ofs + i] &= ~WM_VOL_MUTE;
 562                        spec->vol[ofs + i] |=
 563                                ucontrol->value.integer.value[i] ? 0 :
 564                                WM_VOL_MUTE;
 565                        wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
 566                                        spec->master[i]);
 567                        change = 1;
 568                }
 569        }
 570        snd_ice1712_restore_gpio_status(ice);
 571
 572        return change;
 573}
 574
 575/*
 576 * WM8770 master mute control
 577 */
 578#define wm_master_mute_info             snd_ctl_boolean_stereo_info
 579
 580static int wm_master_mute_get(struct snd_kcontrol *kcontrol,
 581                                struct snd_ctl_elem_value *ucontrol)
 582{
 583        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 584        struct phase28_spec *spec = ice->spec;
 585
 586        ucontrol->value.integer.value[0] =
 587                (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
 588        ucontrol->value.integer.value[1] =
 589                (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
 590        return 0;
 591}
 592
 593static int wm_master_mute_put(struct snd_kcontrol *kcontrol,
 594                                struct snd_ctl_elem_value *ucontrol)
 595{
 596        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 597        struct phase28_spec *spec = ice->spec;
 598        int change = 0, i;
 599
 600        snd_ice1712_save_gpio_status(ice);
 601        for (i = 0; i < 2; i++) {
 602                int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
 603                if (ucontrol->value.integer.value[i] != val) {
 604                        int dac;
 605                        spec->master[i] &= ~WM_VOL_MUTE;
 606                        spec->master[i] |=
 607                                ucontrol->value.integer.value[i] ? 0 :
 608                                WM_VOL_MUTE;
 609                        for (dac = 0; dac < ice->num_total_dacs; dac += 2)
 610                                wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
 611                                                spec->vol[dac + i],
 612                                                spec->master[i]);
 613                        change = 1;
 614                }
 615        }
 616        snd_ice1712_restore_gpio_status(ice);
 617
 618        return change;
 619}
 620
 621/* digital master volume */
 622#define PCM_0dB 0xff
 623#define PCM_RES 128     /* -64dB */
 624#define PCM_MIN (PCM_0dB - PCM_RES)
 625static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol,
 626                                struct snd_ctl_elem_info *uinfo)
 627{
 628        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 629        uinfo->count = 1;
 630        uinfo->value.integer.min = 0;           /* mute (-64dB) */
 631        uinfo->value.integer.max = PCM_RES;     /* 0dB */
 632        return 0;
 633}
 634
 635static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol,
 636                                struct snd_ctl_elem_value *ucontrol)
 637{
 638        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 639        unsigned short val;
 640
 641        mutex_lock(&ice->gpio_mutex);
 642        val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
 643        val = val > PCM_MIN ? (val - PCM_MIN) : 0;
 644        ucontrol->value.integer.value[0] = val;
 645        mutex_unlock(&ice->gpio_mutex);
 646        return 0;
 647}
 648
 649static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol,
 650                                struct snd_ctl_elem_value *ucontrol)
 651{
 652        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 653        unsigned short ovol, nvol;
 654        int change = 0;
 655
 656        nvol = ucontrol->value.integer.value[0];
 657        if (nvol > PCM_RES)
 658                return -EINVAL;
 659        snd_ice1712_save_gpio_status(ice);
 660        nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
 661        ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
 662        if (ovol != nvol) {
 663                wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
 664                /* update */
 665                wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
 666                change = 1;
 667        }
 668        snd_ice1712_restore_gpio_status(ice);
 669        return change;
 670}
 671
 672/*
 673 * Deemphasis
 674 */
 675#define phase28_deemp_info      snd_ctl_boolean_mono_info
 676
 677static int phase28_deemp_get(struct snd_kcontrol *kcontrol,
 678                                struct snd_ctl_elem_value *ucontrol)
 679{
 680        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 681        ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) ==
 682                                                0xf;
 683        return 0;
 684}
 685
 686static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
 687                                struct snd_ctl_elem_value *ucontrol)
 688{
 689        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 690        int temp, temp2;
 691        temp = wm_get(ice, WM_DAC_CTRL2);
 692        temp2 = temp;
 693        if (ucontrol->value.integer.value[0])
 694                temp |= 0xf;
 695        else
 696                temp &= ~0xf;
 697        if (temp != temp2) {
 698                wm_put(ice, WM_DAC_CTRL2, temp);
 699                return 1;
 700        }
 701        return 0;
 702}
 703
 704/*
 705 * ADC Oversampling
 706 */
 707static int phase28_oversampling_info(struct snd_kcontrol *k,
 708                                        struct snd_ctl_elem_info *uinfo)
 709{
 710        static const char * const texts[2] = { "128x", "64x"    };
 711
 712        return snd_ctl_enum_info(uinfo, 1, 2, texts);
 713}
 714
 715static int phase28_oversampling_get(struct snd_kcontrol *kcontrol,
 716                                        struct snd_ctl_elem_value *ucontrol)
 717{
 718        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 719        ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) ==
 720                                                0x8;
 721        return 0;
 722}
 723
 724static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
 725                                        struct snd_ctl_elem_value *ucontrol)
 726{
 727        int temp, temp2;
 728        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 729
 730        temp = wm_get(ice, WM_MASTER);
 731        temp2 = temp;
 732
 733        if (ucontrol->value.enumerated.item[0])
 734                temp |= 0x8;
 735        else
 736                temp &= ~0x8;
 737
 738        if (temp != temp2) {
 739                wm_put(ice, WM_MASTER, temp);
 740                return 1;
 741        }
 742        return 0;
 743}
 744
 745static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 746static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
 747
 748static const struct snd_kcontrol_new phase28_dac_controls[] = {
 749        {
 750                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 751                .name = "Master Playback Switch",
 752                .info = wm_master_mute_info,
 753                .get = wm_master_mute_get,
 754                .put = wm_master_mute_put
 755        },
 756        {
 757                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 758                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 759                           SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 760                .name = "Master Playback Volume",
 761                .info = wm_master_vol_info,
 762                .get = wm_master_vol_get,
 763                .put = wm_master_vol_put,
 764                .tlv = { .p = db_scale_wm_dac }
 765        },
 766        {
 767                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 768                .name = "Front Playback Switch",
 769                .info = wm_mute_info,
 770                .get = wm_mute_get,
 771                .put = wm_mute_put,
 772                .private_value = (2 << 8) | 0
 773        },
 774        {
 775                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 776                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 777                           SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 778                .name = "Front Playback Volume",
 779                .info = wm_vol_info,
 780                .get = wm_vol_get,
 781                .put = wm_vol_put,
 782                .private_value = (2 << 8) | 0,
 783                .tlv = { .p = db_scale_wm_dac }
 784        },
 785        {
 786                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 787                .name = "Rear Playback Switch",
 788                .info = wm_mute_info,
 789                .get = wm_mute_get,
 790                .put = wm_mute_put,
 791                .private_value = (2 << 8) | 2
 792        },
 793        {
 794                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 795                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 796                           SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 797                .name = "Rear Playback Volume",
 798                .info = wm_vol_info,
 799                .get = wm_vol_get,
 800                .put = wm_vol_put,
 801                .private_value = (2 << 8) | 2,
 802                .tlv = { .p = db_scale_wm_dac }
 803        },
 804        {
 805                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 806                .name = "Center Playback Switch",
 807                .info = wm_mute_info,
 808                .get = wm_mute_get,
 809                .put = wm_mute_put,
 810                .private_value = (1 << 8) | 4
 811        },
 812        {
 813                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 814                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 815                           SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 816                .name = "Center Playback Volume",
 817                .info = wm_vol_info,
 818                .get = wm_vol_get,
 819                .put = wm_vol_put,
 820                .private_value = (1 << 8) | 4,
 821                .tlv = { .p = db_scale_wm_dac }
 822        },
 823        {
 824                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 825                .name = "LFE Playback Switch",
 826                .info = wm_mute_info,
 827                .get = wm_mute_get,
 828                .put = wm_mute_put,
 829                .private_value = (1 << 8) | 5
 830        },
 831        {
 832                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 833                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 834                           SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 835                .name = "LFE Playback Volume",
 836                .info = wm_vol_info,
 837                .get = wm_vol_get,
 838                .put = wm_vol_put,
 839                .private_value = (1 << 8) | 5,
 840                .tlv = { .p = db_scale_wm_dac }
 841        },
 842        {
 843                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 844                .name = "Side Playback Switch",
 845                .info = wm_mute_info,
 846                .get = wm_mute_get,
 847                .put = wm_mute_put,
 848                .private_value = (2 << 8) | 6
 849        },
 850        {
 851                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 852                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 853                           SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 854                .name = "Side Playback Volume",
 855                .info = wm_vol_info,
 856                .get = wm_vol_get,
 857                .put = wm_vol_put,
 858                .private_value = (2 << 8) | 6,
 859                .tlv = { .p = db_scale_wm_dac }
 860        }
 861};
 862
 863static const struct snd_kcontrol_new wm_controls[] = {
 864        {
 865                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 866                .name = "PCM Playback Switch",
 867                .info = wm_pcm_mute_info,
 868                .get = wm_pcm_mute_get,
 869                .put = wm_pcm_mute_put
 870        },
 871        {
 872                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 873                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 874                           SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 875                .name = "PCM Playback Volume",
 876                .info = wm_pcm_vol_info,
 877                .get = wm_pcm_vol_get,
 878                .put = wm_pcm_vol_put,
 879                .tlv = { .p = db_scale_wm_pcm }
 880        },
 881        {
 882                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 883                .name = "DAC Deemphasis Switch",
 884                .info = phase28_deemp_info,
 885                .get = phase28_deemp_get,
 886                .put = phase28_deemp_put
 887        },
 888        {
 889                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 890                .name = "ADC Oversampling",
 891                .info = phase28_oversampling_info,
 892                .get = phase28_oversampling_get,
 893                .put = phase28_oversampling_put
 894        }
 895};
 896
 897static int phase28_add_controls(struct snd_ice1712 *ice)
 898{
 899        unsigned int i, counts;
 900        int err;
 901
 902        counts = ARRAY_SIZE(phase28_dac_controls);
 903        for (i = 0; i < counts; i++) {
 904                err = snd_ctl_add(ice->card,
 905                                        snd_ctl_new1(&phase28_dac_controls[i],
 906                                                        ice));
 907                if (err < 0)
 908                        return err;
 909        }
 910
 911        for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
 912                err = snd_ctl_add(ice->card,
 913                                        snd_ctl_new1(&wm_controls[i], ice));
 914                if (err < 0)
 915                        return err;
 916        }
 917
 918        return 0;
 919}
 920
 921struct snd_ice1712_card_info snd_vt1724_phase_cards[] = {
 922        {
 923                .subvendor = VT1724_SUBDEVICE_PHASE22,
 924                .name = "Terratec PHASE 22",
 925                .model = "phase22",
 926                .chip_init = phase22_init,
 927                .build_controls = phase22_add_controls,
 928                .eeprom_size = sizeof(phase22_eeprom),
 929                .eeprom_data = phase22_eeprom,
 930        },
 931        {
 932                .subvendor = VT1724_SUBDEVICE_PHASE28,
 933                .name = "Terratec PHASE 28",
 934                .model = "phase28",
 935                .chip_init = phase28_init,
 936                .build_controls = phase28_add_controls,
 937                .eeprom_size = sizeof(phase28_eeprom),
 938                .eeprom_data = phase28_eeprom,
 939        },
 940        {
 941                .subvendor = VT1724_SUBDEVICE_TS22,
 942                .name = "Terrasoniq TS22 PCI",
 943                .model = "TS22",
 944                .chip_init = phase22_init,
 945                .build_controls = phase22_add_controls,
 946                .eeprom_size = sizeof(phase22_eeprom),
 947                .eeprom_data = phase22_eeprom,
 948        },
 949        { } /* terminator */
 950};
 951