cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phase.c (25051B)


      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};