FILE
phase.c
File preview with syntax highlighting.
linux-6.19.14/sound/pci/ice1712/phase.c
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 guard(mutex)(&ice->gpio_mutex); 291 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 292 0 : 1; 293 return 0; 294} 295 296static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, 297 struct snd_ctl_elem_value *ucontrol) 298{ 299 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 300 unsigned short nval, oval; 301 int change; 302 303 snd_ice1712_save_gpio_status(ice); 304 oval = wm_get(ice, WM_MUTE); 305 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10); 306 change = (nval != oval); 307 if (change) 308 wm_put(ice, WM_MUTE, nval); 309 snd_ice1712_restore_gpio_status(ice); 310 311 return change; 312} 313 314/* 315 * Master volume attenuation mixer control 316 */ 317static int wm_master_vol_info(struct snd_kcontrol *kcontrol, 318 struct snd_ctl_elem_info *uinfo) 319{ 320 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 321 uinfo->count = 2; 322 uinfo->value.integer.min = 0; 323 uinfo->value.integer.max = WM_VOL_MAX; 324 return 0; 325} 326 327static int wm_master_vol_get(struct snd_kcontrol *kcontrol, 328 struct snd_ctl_elem_value *ucontrol) 329{ 330 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 331 struct phase28_spec *spec = ice->spec; 332 int i; 333 for (i = 0; i < 2; i++) 334 ucontrol->value.integer.value[i] = spec->master[i] & 335 ~WM_VOL_MUTE; 336 return 0; 337} 338 339static int wm_master_vol_put(struct snd_kcontrol *kcontrol, 340 struct snd_ctl_elem_value *ucontrol) 341{ 342 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 343 struct phase28_spec *spec = ice->spec; 344 int ch, change = 0; 345 346 snd_ice1712_save_gpio_status(ice); 347 for (ch = 0; ch < 2; ch++) { 348 unsigned int vol = ucontrol->value.integer.value[ch]; 349 if (vol > WM_VOL_MAX) 350 continue; 351 vol |= spec->master[ch] & WM_VOL_MUTE; 352 if (vol != spec->master[ch]) { 353 int dac; 354 spec->master[ch] = vol; 355 for (dac = 0; dac < ice->num_total_dacs; dac += 2) 356 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, 357 spec->vol[dac + ch], 358 spec->master[ch]); 359 change = 1; 360 } 361 } 362 snd_ice1712_restore_gpio_status(ice); 363 return change; 364} 365 366static int phase28_init(struct snd_ice1712 *ice) 367{ 368 static const unsigned short wm_inits_phase28[] = { 369 /* These come first to reduce init pop noise */ 370 0x1b, 0x044, /* ADC Mux (AC'97 source) */ 371 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ 372 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ 373 374 0x18, 0x000, /* All power-up */ 375 376 0x16, 0x122, /* I2S, normal polarity, 24bit */ 377 0x17, 0x022, /* 256fs, slave mode */ 378 0x00, 0, /* DAC1 analog mute */ 379 0x01, 0, /* DAC2 analog mute */ 380 0x02, 0, /* DAC3 analog mute */ 381 0x03, 0, /* DAC4 analog mute */ 382 0x04, 0, /* DAC5 analog mute */ 383 0x05, 0, /* DAC6 analog mute */ 384 0x06, 0, /* DAC7 analog mute */ 385 0x07, 0, /* DAC8 analog mute */ 386 0x08, 0x100, /* master analog mute */ 387 0x09, 0xff, /* DAC1 digital full */ 388 0x0a, 0xff, /* DAC2 digital full */ 389 0x0b, 0xff, /* DAC3 digital full */ 390 0x0c, 0xff, /* DAC4 digital full */ 391 0x0d, 0xff, /* DAC5 digital full */ 392 0x0e, 0xff, /* DAC6 digital full */ 393 0x0f, 0xff, /* DAC7 digital full */ 394 0x10, 0xff, /* DAC8 digital full */ 395 0x11, 0x1ff, /* master digital full */ 396 0x12, 0x000, /* phase normal */ 397 0x13, 0x090, /* unmute DAC L/R */ 398 0x14, 0x000, /* all unmute */ 399 0x15, 0x000, /* no deemphasis, no ZFLG */ 400 0x19, 0x000, /* -12dB ADC/L */ 401 0x1a, 0x000, /* -12dB ADC/R */ 402 (unsigned short)-1 403 }; 404 405 unsigned int tmp; 406 struct snd_akm4xxx *ak; 407 struct phase28_spec *spec; 408 const unsigned short *p; 409 int i; 410 411 ice->num_total_dacs = 8; 412 ice->num_total_adcs = 2; 413 414 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 415 if (!spec) 416 return -ENOMEM; 417 ice->spec = spec; 418 419 /* Initialize analog chips */ 420 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL); 421 ak = ice->akm; 422 if (!ak) 423 return -ENOMEM; 424 ice->akm_codecs = 1; 425 426 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */ 427 428 /* reset the wm codec as the SPI mode */ 429 snd_ice1712_save_gpio_status(ice); 430 snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS| 431 PHASE28_HP_SEL)); 432 433 tmp = snd_ice1712_gpio_read(ice); 434 tmp &= ~PHASE28_WM_RESET; 435 snd_ice1712_gpio_write(ice, tmp); 436 udelay(1); 437 tmp |= PHASE28_WM_CS; 438 snd_ice1712_gpio_write(ice, tmp); 439 udelay(1); 440 tmp |= PHASE28_WM_RESET; 441 snd_ice1712_gpio_write(ice, tmp); 442 udelay(1); 443 444 p = wm_inits_phase28; 445 for (; *p != (unsigned short)-1; p += 2) 446 wm_put(ice, p[0], p[1]); 447 448 snd_ice1712_restore_gpio_status(ice); 449 450 spec->master[0] = WM_VOL_MUTE; 451 spec->master[1] = WM_VOL_MUTE; 452 for (i = 0; i < ice->num_total_dacs; i++) { 453 spec->vol[i] = WM_VOL_MUTE; 454 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); 455 } 456 457 return 0; 458} 459 460/* 461 * DAC volume attenuation mixer control 462 */ 463static int wm_vol_info(struct snd_kcontrol *kcontrol, 464 struct snd_ctl_elem_info *uinfo) 465{ 466 int voices = kcontrol->private_value >> 8; 467 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 468 uinfo->count = voices; 469 uinfo->value.integer.min = 0; /* mute (-101dB) */ 470 uinfo->value.integer.max = 0x7F; /* 0dB */ 471 return 0; 472} 473 474static int wm_vol_get(struct snd_kcontrol *kcontrol, 475 struct snd_ctl_elem_value *ucontrol) 476{ 477 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 478 struct phase28_spec *spec = ice->spec; 479 int i, ofs, voices; 480 481 voices = kcontrol->private_value >> 8; 482 ofs = kcontrol->private_value & 0xff; 483 for (i = 0; i < voices; i++) 484 ucontrol->value.integer.value[i] = 485 spec->vol[ofs+i] & ~WM_VOL_MUTE; 486 return 0; 487} 488 489static int wm_vol_put(struct snd_kcontrol *kcontrol, 490 struct snd_ctl_elem_value *ucontrol) 491{ 492 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 493 struct phase28_spec *spec = ice->spec; 494 int i, idx, ofs, voices; 495 int change = 0; 496 497 voices = kcontrol->private_value >> 8; 498 ofs = kcontrol->private_value & 0xff; 499 snd_ice1712_save_gpio_status(ice); 500 for (i = 0; i < voices; i++) { 501 unsigned int vol; 502 vol = ucontrol->value.integer.value[i]; 503 if (vol > 0x7f) 504 continue; 505 vol |= spec->vol[ofs+i] & WM_VOL_MUTE; 506 if (vol != spec->vol[ofs+i]) { 507 spec->vol[ofs+i] = vol; 508 idx = WM_DAC_ATTEN + ofs + i; 509 wm_set_vol(ice, idx, spec->vol[ofs+i], 510 spec->master[i]); 511 change = 1; 512 } 513 } 514 snd_ice1712_restore_gpio_status(ice); 515 return change; 516} 517 518/* 519 * WM8770 mute control 520 */ 521static int wm_mute_info(struct snd_kcontrol *kcontrol, 522 struct snd_ctl_elem_info *uinfo) { 523 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 524 uinfo->count = kcontrol->private_value >> 8; 525 uinfo->value.integer.min = 0; 526 uinfo->value.integer.max = 1; 527 return 0; 528} 529 530static int wm_mute_get(struct snd_kcontrol *kcontrol, 531 struct snd_ctl_elem_value *ucontrol) 532{ 533 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 534 struct phase28_spec *spec = ice->spec; 535 int voices, ofs, i; 536 537 voices = kcontrol->private_value >> 8; 538 ofs = kcontrol->private_value & 0xFF; 539 540 for (i = 0; i < voices; i++) 541 ucontrol->value.integer.value[i] = 542 (spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1; 543 return 0; 544} 545 546static int wm_mute_put(struct snd_kcontrol *kcontrol, 547 struct snd_ctl_elem_value *ucontrol) 548{ 549 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 550 struct phase28_spec *spec = ice->spec; 551 int change = 0, voices, ofs, i; 552 553 voices = kcontrol->private_value >> 8; 554 ofs = kcontrol->private_value & 0xFF; 555 556 snd_ice1712_save_gpio_status(ice); 557 for (i = 0; i < voices; i++) { 558 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; 559 if (ucontrol->value.integer.value[i] != val) { 560 spec->vol[ofs + i] &= ~WM_VOL_MUTE; 561 spec->vol[ofs + i] |= 562 ucontrol->value.integer.value[i] ? 0 : 563 WM_VOL_MUTE; 564 wm_set_vol(ice, ofs + i, spec->vol[ofs + i], 565 spec->master[i]); 566 change = 1; 567 } 568 } 569 snd_ice1712_restore_gpio_status(ice); 570 571 return change; 572} 573 574/* 575 * WM8770 master mute control 576 */ 577#define wm_master_mute_info snd_ctl_boolean_stereo_info 578 579static int wm_master_mute_get(struct snd_kcontrol *kcontrol, 580 struct snd_ctl_elem_value *ucontrol) 581{ 582 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 583 struct phase28_spec *spec = ice->spec; 584 585 ucontrol->value.integer.value[0] = 586 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1; 587 ucontrol->value.integer.value[1] = 588 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1; 589 return 0; 590} 591 592static int wm_master_mute_put(struct snd_kcontrol *kcontrol, 593 struct snd_ctl_elem_value *ucontrol) 594{ 595 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 596 struct phase28_spec *spec = ice->spec; 597 int change = 0, i; 598 599 snd_ice1712_save_gpio_status(ice); 600 for (i = 0; i < 2; i++) { 601 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1; 602 if (ucontrol->value.integer.value[i] != val) { 603 int dac; 604 spec->master[i] &= ~WM_VOL_MUTE; 605 spec->master[i] |= 606 ucontrol->value.integer.value[i] ? 0 : 607 WM_VOL_MUTE; 608 for (dac = 0; dac < ice->num_total_dacs; dac += 2) 609 wm_set_vol(ice, WM_DAC_ATTEN + dac + i, 610 spec->vol[dac + i], 611 spec->master[i]); 612 change = 1; 613 } 614 } 615 snd_ice1712_restore_gpio_status(ice); 616 617 return change; 618} 619 620/* digital master volume */ 621#define PCM_0dB 0xff 622#define PCM_RES 128 /* -64dB */ 623#define PCM_MIN (PCM_0dB - PCM_RES) 624static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, 625 struct snd_ctl_elem_info *uinfo) 626{ 627 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 628 uinfo->count = 1; 629 uinfo->value.integer.min = 0; /* mute (-64dB) */ 630 uinfo->value.integer.max = PCM_RES; /* 0dB */ 631 return 0; 632} 633 634static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, 635 struct snd_ctl_elem_value *ucontrol) 636{ 637 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 638 unsigned short val; 639 640 guard(mutex)(&ice->gpio_mutex); 641 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; 642 val = val > PCM_MIN ? (val - PCM_MIN) : 0; 643 ucontrol->value.integer.value[0] = val; 644 return 0; 645} 646 647static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, 648 struct snd_ctl_elem_value *ucontrol) 649{ 650 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 651 unsigned short ovol, nvol; 652 int change = 0; 653 654 nvol = ucontrol->value.integer.value[0]; 655 if (nvol > PCM_RES) 656 return -EINVAL; 657 snd_ice1712_save_gpio_status(ice); 658 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; 659 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; 660 if (ovol != nvol) { 661 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */ 662 /* update */ 663 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); 664 change = 1; 665 } 666 snd_ice1712_restore_gpio_status(ice); 667 return change; 668} 669 670/* 671 * Deemphasis 672 */ 673#define phase28_deemp_info snd_ctl_boolean_mono_info 674 675static int phase28_deemp_get(struct snd_kcontrol *kcontrol, 676 struct snd_ctl_elem_value *ucontrol) 677{ 678 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 679 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 680 0xf; 681 return 0; 682} 683 684static int phase28_deemp_put(struct snd_kcontrol *kcontrol, 685 struct snd_ctl_elem_value *ucontrol) 686{ 687 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 688 int temp, temp2; 689 temp = wm_get(ice, WM_DAC_CTRL2); 690 temp2 = temp; 691 if (ucontrol->value.integer.value[0]) 692 temp |= 0xf; 693 else 694 temp &= ~0xf; 695 if (temp != temp2) { 696 wm_put(ice, WM_DAC_CTRL2, temp); 697 return 1; 698 } 699 return 0; 700} 701 702/* 703 * ADC Oversampling 704 */ 705static int phase28_oversampling_info(struct snd_kcontrol *k, 706 struct snd_ctl_elem_info *uinfo) 707{ 708 static const char * const texts[2] = { "128x", "64x" }; 709 710 return snd_ctl_enum_info(uinfo, 1, 2, texts); 711} 712 713static int phase28_oversampling_get(struct snd_kcontrol *kcontrol, 714 struct snd_ctl_elem_value *ucontrol) 715{ 716 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 717 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 718 0x8; 719 return 0; 720} 721 722static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, 723 struct snd_ctl_elem_value *ucontrol) 724{ 725 int temp, temp2; 726 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 727 728 temp = wm_get(ice, WM_MASTER); 729 temp2 = temp; 730 731 if (ucontrol->value.enumerated.item[0]) 732 temp |= 0x8; 733 else 734 temp &= ~0x8; 735 736 if (temp != temp2) { 737 wm_put(ice, WM_MASTER, temp); 738 return 1; 739 } 740 return 0; 741} 742 743static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); 744static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); 745 746static const struct snd_kcontrol_new phase28_dac_controls[] = { 747 { 748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 749 .name = "Master Playback Switch", 750 .info = wm_master_mute_info, 751 .get = wm_master_mute_get, 752 .put = wm_master_mute_put 753 }, 754 { 755 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 756 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 757 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 758 .name = "Master Playback Volume", 759 .info = wm_master_vol_info, 760 .get = wm_master_vol_get, 761 .put = wm_master_vol_put, 762 .tlv = { .p = db_scale_wm_dac } 763 }, 764 { 765 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 766 .name = "Front Playback Switch", 767 .info = wm_mute_info, 768 .get = wm_mute_get, 769 .put = wm_mute_put, 770 .private_value = (2 << 8) | 0 771 }, 772 { 773 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 774 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 775 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 776 .name = "Front Playback Volume", 777 .info = wm_vol_info, 778 .get = wm_vol_get, 779 .put = wm_vol_put, 780 .private_value = (2 << 8) | 0, 781 .tlv = { .p = db_scale_wm_dac } 782 }, 783 { 784 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 785 .name = "Rear Playback Switch", 786 .info = wm_mute_info, 787 .get = wm_mute_get, 788 .put = wm_mute_put, 789 .private_value = (2 << 8) | 2 790 }, 791 { 792 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 793 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 794 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 795 .name = "Rear Playback Volume", 796 .info = wm_vol_info, 797 .get = wm_vol_get, 798 .put = wm_vol_put, 799 .private_value = (2 << 8) | 2, 800 .tlv = { .p = db_scale_wm_dac } 801 }, 802 { 803 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 804 .name = "Center Playback Switch", 805 .info = wm_mute_info, 806 .get = wm_mute_get, 807 .put = wm_mute_put, 808 .private_value = (1 << 8) | 4 809 }, 810 { 811 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 812 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 813 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 814 .name = "Center Playback Volume", 815 .info = wm_vol_info, 816 .get = wm_vol_get, 817 .put = wm_vol_put, 818 .private_value = (1 << 8) | 4, 819 .tlv = { .p = db_scale_wm_dac } 820 }, 821 { 822 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 823 .name = "LFE Playback Switch", 824 .info = wm_mute_info, 825 .get = wm_mute_get, 826 .put = wm_mute_put, 827 .private_value = (1 << 8) | 5 828 }, 829 { 830 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 831 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 832 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 833 .name = "LFE Playback Volume", 834 .info = wm_vol_info, 835 .get = wm_vol_get, 836 .put = wm_vol_put, 837 .private_value = (1 << 8) | 5, 838 .tlv = { .p = db_scale_wm_dac } 839 }, 840 { 841 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 842 .name = "Side Playback Switch", 843 .info = wm_mute_info, 844 .get = wm_mute_get, 845 .put = wm_mute_put, 846 .private_value = (2 << 8) | 6 847 }, 848 { 849 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 850 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 851 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 852 .name = "Side Playback Volume", 853 .info = wm_vol_info, 854 .get = wm_vol_get, 855 .put = wm_vol_put, 856 .private_value = (2 << 8) | 6, 857 .tlv = { .p = db_scale_wm_dac } 858 } 859}; 860 861static const struct snd_kcontrol_new wm_controls[] = { 862 { 863 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 864 .name = "PCM Playback Switch", 865 .info = wm_pcm_mute_info, 866 .get = wm_pcm_mute_get, 867 .put = wm_pcm_mute_put 868 }, 869 { 870 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 871 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 872 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 873 .name = "PCM Playback Volume", 874 .info = wm_pcm_vol_info, 875 .get = wm_pcm_vol_get, 876 .put = wm_pcm_vol_put, 877 .tlv = { .p = db_scale_wm_pcm } 878 }, 879 { 880 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 881 .name = "DAC Deemphasis Switch", 882 .info = phase28_deemp_info, 883 .get = phase28_deemp_get, 884 .put = phase28_deemp_put 885 }, 886 { 887 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 888 .name = "ADC Oversampling", 889 .info = phase28_oversampling_info, 890 .get = phase28_oversampling_get, 891 .put = phase28_oversampling_put 892 } 893}; 894 895static int phase28_add_controls(struct snd_ice1712 *ice) 896{ 897 unsigned int i, counts; 898 int err; 899 900 counts = ARRAY_SIZE(phase28_dac_controls); 901 for (i = 0; i < counts; i++) { 902 err = snd_ctl_add(ice->card, 903 snd_ctl_new1(&phase28_dac_controls[i], 904 ice)); 905 if (err < 0) 906 return err; 907 } 908 909 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) { 910 err = snd_ctl_add(ice->card, 911 snd_ctl_new1(&wm_controls[i], ice)); 912 if (err < 0) 913 return err; 914 } 915 916 return 0; 917} 918 919struct snd_ice1712_card_info snd_vt1724_phase_cards[] = { 920 { 921 .subvendor = VT1724_SUBDEVICE_PHASE22, 922 .name = "Terratec PHASE 22", 923 .model = "phase22", 924 .chip_init = phase22_init, 925 .build_controls = phase22_add_controls, 926 .eeprom_size = sizeof(phase22_eeprom), 927 .eeprom_data = phase22_eeprom, 928 }, 929 { 930 .subvendor = VT1724_SUBDEVICE_PHASE28, 931 .name = "Terratec PHASE 28", 932 .model = "phase28", 933 .chip_init = phase28_init, 934 .build_controls = phase28_add_controls, 935 .eeprom_size = sizeof(phase28_eeprom), 936 .eeprom_data = phase28_eeprom, 937 }, 938 { 939 .subvendor = VT1724_SUBDEVICE_TS22, 940 .name = "Terrasoniq TS22 PCI", 941 .model = "TS22", 942 .chip_init = phase22_init, 943 .build_controls = phase22_add_controls, 944 .eeprom_size = sizeof(phase22_eeprom), 945 .eeprom_data = phase22_eeprom, 946 }, 947 { } /* terminator */ 948};
~/
Read-only file preview.