951 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ALSA driver for ICEnsemble ICE1724 (Envy24)4 *5 * Lowlevel functions for Terratec PHASE 226 *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 CS841615 * (support status unknown, please test and report)16 *17 * Envy connects to AK452418 * - CS directly from GPIO 1019 * - CCLK via 74HCT125's gate #4 from GPIO 420 * - CDTI via 74HCT125's gate #2 from GPIO 521 * CDTI may be completely blocked by 74HCT125's gate #122 * controlled by GPIO 323 */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 WM877071 * 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, 086};87 88#define WM_VOL_MAX (sizeof(wm_vol) - 1)89#define WM_VOL_MUTE 0x800090 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 mode196 */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 else219 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 codec238 */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 codec248 */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 it256 */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 else273 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 control282 */283#define wm_pcm_mute_info snd_ctl_boolean_mono_info284 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 control317 */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)-1404 };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 control463 */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 control521 */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 control577 */578#define wm_master_mute_info snd_ctl_boolean_stereo_info579 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 0xff623#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 * Deemphasis674 */675#define phase28_deemp_info snd_ctl_boolean_mono_info676 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 else696 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 Oversampling706 */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 else736 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_put755 },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) | 0773 },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) | 2792 },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) | 4811 },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) | 5830 },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) | 6849 },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_put870 },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_put887 },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_put894 }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