|
|
|
@ -37,7 +37,7 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* PHASE 28 overview:
|
|
|
|
|
* Audio controller: VIA Envy24HT (full untrimmed version, 8in/8out)
|
|
|
|
|
* Audio controller: VIA Envy24HT (full untrimmed version, 4in/8out)
|
|
|
|
|
* Analog chip: WM8770 (8 channel 192k DAC, 2 channel 96k ADC)
|
|
|
|
|
* Digital receiver: CS8414-CS (supported in this release)
|
|
|
|
|
*/
|
|
|
|
@ -86,18 +86,18 @@ struct phase28_spec {
|
|
|
|
|
* Computed as 20 * Log10(255 / x)
|
|
|
|
|
*/
|
|
|
|
|
static const unsigned char wm_vol[256] = {
|
|
|
|
|
127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
|
|
|
|
|
23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
|
|
|
|
|
17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
|
|
|
|
|
13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
|
|
|
|
|
11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
|
|
|
|
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
|
|
|
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
|
|
|
5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
|
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
|
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
|
0, 0
|
|
|
|
|
127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24,
|
|
|
|
|
24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18,
|
|
|
|
|
17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14,
|
|
|
|
|
14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
|
|
|
|
|
11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9,
|
|
|
|
|
9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
|
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
|
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
|
|
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
|
|
|
|
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
|
|
|
2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define WM_VOL_MAX (sizeof(wm_vol) - 1)
|
|
|
|
@ -126,28 +126,31 @@ static int __devinit phase22_init(struct snd_ice1712 *ice)
|
|
|
|
|
struct snd_akm4xxx *ak;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
// Configure DAC/ADC description for generic part of ice1724
|
|
|
|
|
/* Configure DAC/ADC description for generic part of ice1724 */
|
|
|
|
|
switch (ice->eeprom.subvendor) {
|
|
|
|
|
case VT1724_SUBDEVICE_PHASE22:
|
|
|
|
|
case VT1724_SUBDEVICE_TS22:
|
|
|
|
|
ice->num_total_dacs = 2;
|
|
|
|
|
ice->num_total_adcs = 2;
|
|
|
|
|
ice->vt1720 = 1; // Envy24HT-S have 16 bit wide GPIO
|
|
|
|
|
ice->vt1720 = 1; /* Envy24HT-S have 16 bit wide GPIO */
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
snd_BUG();
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize analog chips
|
|
|
|
|
ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
|
|
|
|
|
if (! ak)
|
|
|
|
|
/* Initialize analog chips */
|
|
|
|
|
ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
|
|
|
|
|
ak = ice->akm;
|
|
|
|
|
if (!ak)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
ice->akm_codecs = 1;
|
|
|
|
|
switch (ice->eeprom.subvendor) {
|
|
|
|
|
case VT1724_SUBDEVICE_PHASE22:
|
|
|
|
|
case VT1724_SUBDEVICE_TS22:
|
|
|
|
|
if ((err = snd_ice1712_akm4xxx_init(ak, &akm_phase22, &akm_phase22_priv, ice)) < 0)
|
|
|
|
|
err = snd_ice1712_akm4xxx_init(ak, &akm_phase22,
|
|
|
|
|
&akm_phase22_priv, ice);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -206,15 +209,16 @@ static unsigned char phase28_eeprom[] __devinitdata = {
|
|
|
|
|
/*
|
|
|
|
|
* write data in the SPI mode
|
|
|
|
|
*/
|
|
|
|
|
static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
|
|
|
|
|
static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs,
|
|
|
|
|
unsigned int data, int bits)
|
|
|
|
|
{
|
|
|
|
|
unsigned int tmp;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
tmp = snd_ice1712_gpio_read(ice);
|
|
|
|
|
|
|
|
|
|
snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK|
|
|
|
|
|
PHASE28_WM_CS));
|
|
|
|
|
snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|
|
|
|
|
|
PHASE28_SPI_CLK|PHASE28_WM_CS));
|
|
|
|
|
tmp |= PHASE28_WM_RW;
|
|
|
|
|
tmp &= ~cs;
|
|
|
|
|
snd_ice1712_gpio_write(ice, tmp);
|
|
|
|
@ -273,14 +277,16 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
|
|
|
|
|
ice->akm[0].images[reg + 1] = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
|
|
|
|
|
static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
|
|
|
|
|
unsigned short vol, unsigned short master)
|
|
|
|
|
{
|
|
|
|
|
unsigned char nvol;
|
|
|
|
|
|
|
|
|
|
if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
|
|
|
|
|
nvol = 0;
|
|
|
|
|
else
|
|
|
|
|
nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
|
|
|
|
|
nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) *
|
|
|
|
|
(master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
|
|
|
|
|
|
|
|
|
|
wm_put(ice, index, nvol);
|
|
|
|
|
wm_put_nocache(ice, index, 0x180 | nvol);
|
|
|
|
@ -291,17 +297,20 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho
|
|
|
|
|
*/
|
|
|
|
|
#define wm_pcm_mute_info snd_ctl_boolean_mono_info
|
|
|
|
|
|
|
|
|
|
static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&ice->gpio_mutex);
|
|
|
|
|
ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
|
|
|
|
|
ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ?
|
|
|
|
|
0 : 1;
|
|
|
|
|
mutex_unlock(&ice->gpio_mutex);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
unsigned short nval, oval;
|
|
|
|
@ -310,7 +319,8 @@ static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
|
|
|
|
|
snd_ice1712_save_gpio_status(ice);
|
|
|
|
|
oval = wm_get(ice, WM_MUTE);
|
|
|
|
|
nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
|
|
|
|
|
if ((change = (nval != oval)))
|
|
|
|
|
change = (nval != oval);
|
|
|
|
|
if (change)
|
|
|
|
|
wm_put(ice, WM_MUTE, nval);
|
|
|
|
|
snd_ice1712_restore_gpio_status(ice);
|
|
|
|
|
|
|
|
|
@ -320,7 +330,8 @@ static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va
|
|
|
|
|
/*
|
|
|
|
|
* Master volume attenuation mixer control
|
|
|
|
|
*/
|
|
|
|
|
static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
{
|
|
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
|
|
|
|
uinfo->count = 2;
|
|
|
|
@ -329,17 +340,20 @@ static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
|
int i;
|
|
|
|
|
for (i=0; i<2; i++)
|
|
|
|
|
ucontrol->value.integer.value[i] = spec->master[i] & ~WM_VOL_MUTE;
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
|
ucontrol->value.integer.value[i] = spec->master[i] &
|
|
|
|
|
~WM_VOL_MUTE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
@ -369,38 +383,38 @@ static int __devinit phase28_init(struct snd_ice1712 *ice)
|
|
|
|
|
{
|
|
|
|
|
static const unsigned short wm_inits_phase28[] = {
|
|
|
|
|
/* These come first to reduce init pop noise */
|
|
|
|
|
0x1b, 0x044, /* ADC Mux (AC'97 source) */
|
|
|
|
|
0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
|
|
|
|
|
0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
|
|
|
|
|
0x1b, 0x044, /* ADC Mux (AC'97 source) */
|
|
|
|
|
0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
|
|
|
|
|
0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
|
|
|
|
|
|
|
|
|
|
0x18, 0x000, /* All power-up */
|
|
|
|
|
0x18, 0x000, /* All power-up */
|
|
|
|
|
|
|
|
|
|
0x16, 0x122, /* I2S, normal polarity, 24bit */
|
|
|
|
|
0x17, 0x022, /* 256fs, slave mode */
|
|
|
|
|
0x00, 0, /* DAC1 analog mute */
|
|
|
|
|
0x01, 0, /* DAC2 analog mute */
|
|
|
|
|
0x02, 0, /* DAC3 analog mute */
|
|
|
|
|
0x03, 0, /* DAC4 analog mute */
|
|
|
|
|
0x04, 0, /* DAC5 analog mute */
|
|
|
|
|
0x05, 0, /* DAC6 analog mute */
|
|
|
|
|
0x06, 0, /* DAC7 analog mute */
|
|
|
|
|
0x07, 0, /* DAC8 analog mute */
|
|
|
|
|
0x08, 0x100, /* master analog mute */
|
|
|
|
|
0x09, 0xff, /* DAC1 digital full */
|
|
|
|
|
0x0a, 0xff, /* DAC2 digital full */
|
|
|
|
|
0x0b, 0xff, /* DAC3 digital full */
|
|
|
|
|
0x0c, 0xff, /* DAC4 digital full */
|
|
|
|
|
0x0d, 0xff, /* DAC5 digital full */
|
|
|
|
|
0x0e, 0xff, /* DAC6 digital full */
|
|
|
|
|
0x0f, 0xff, /* DAC7 digital full */
|
|
|
|
|
0x10, 0xff, /* DAC8 digital full */
|
|
|
|
|
0x11, 0x1ff, /* master digital full */
|
|
|
|
|
0x12, 0x000, /* phase normal */
|
|
|
|
|
0x13, 0x090, /* unmute DAC L/R */
|
|
|
|
|
0x14, 0x000, /* all unmute */
|
|
|
|
|
0x15, 0x000, /* no deemphasis, no ZFLG */
|
|
|
|
|
0x19, 0x000, /* -12dB ADC/L */
|
|
|
|
|
0x1a, 0x000, /* -12dB ADC/R */
|
|
|
|
|
0x16, 0x122, /* I2S, normal polarity, 24bit */
|
|
|
|
|
0x17, 0x022, /* 256fs, slave mode */
|
|
|
|
|
0x00, 0, /* DAC1 analog mute */
|
|
|
|
|
0x01, 0, /* DAC2 analog mute */
|
|
|
|
|
0x02, 0, /* DAC3 analog mute */
|
|
|
|
|
0x03, 0, /* DAC4 analog mute */
|
|
|
|
|
0x04, 0, /* DAC5 analog mute */
|
|
|
|
|
0x05, 0, /* DAC6 analog mute */
|
|
|
|
|
0x06, 0, /* DAC7 analog mute */
|
|
|
|
|
0x07, 0, /* DAC8 analog mute */
|
|
|
|
|
0x08, 0x100, /* master analog mute */
|
|
|
|
|
0x09, 0xff, /* DAC1 digital full */
|
|
|
|
|
0x0a, 0xff, /* DAC2 digital full */
|
|
|
|
|
0x0b, 0xff, /* DAC3 digital full */
|
|
|
|
|
0x0c, 0xff, /* DAC4 digital full */
|
|
|
|
|
0x0d, 0xff, /* DAC5 digital full */
|
|
|
|
|
0x0e, 0xff, /* DAC6 digital full */
|
|
|
|
|
0x0f, 0xff, /* DAC7 digital full */
|
|
|
|
|
0x10, 0xff, /* DAC8 digital full */
|
|
|
|
|
0x11, 0x1ff, /* master digital full */
|
|
|
|
|
0x12, 0x000, /* phase normal */
|
|
|
|
|
0x13, 0x090, /* unmute DAC L/R */
|
|
|
|
|
0x14, 0x000, /* all unmute */
|
|
|
|
|
0x15, 0x000, /* no deemphasis, no ZFLG */
|
|
|
|
|
0x19, 0x000, /* -12dB ADC/L */
|
|
|
|
|
0x1a, 0x000, /* -12dB ADC/R */
|
|
|
|
|
(unsigned short)-1
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -418,17 +432,19 @@ static int __devinit phase28_init(struct snd_ice1712 *ice)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
ice->spec = spec;
|
|
|
|
|
|
|
|
|
|
// Initialize analog chips
|
|
|
|
|
ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
|
|
|
|
|
/* Initialize analog chips */
|
|
|
|
|
ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
|
|
|
|
|
ak = ice->akm;
|
|
|
|
|
if (!ak)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
ice->akm_codecs = 1;
|
|
|
|
|
|
|
|
|
|
snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
|
|
|
|
|
snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */
|
|
|
|
|
|
|
|
|
|
/* reset the wm codec as the SPI mode */
|
|
|
|
|
snd_ice1712_save_gpio_status(ice);
|
|
|
|
|
snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL));
|
|
|
|
|
snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|
|
|
|
|
|
PHASE28_HP_SEL));
|
|
|
|
|
|
|
|
|
|
tmp = snd_ice1712_gpio_read(ice);
|
|
|
|
|
tmp &= ~PHASE28_WM_RESET;
|
|
|
|
@ -460,7 +476,8 @@ static int __devinit phase28_init(struct snd_ice1712 *ice)
|
|
|
|
|
/*
|
|
|
|
|
* DAC volume attenuation mixer control
|
|
|
|
|
*/
|
|
|
|
|
static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
static int wm_vol_info(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
{
|
|
|
|
|
int voices = kcontrol->private_value >> 8;
|
|
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
|
|
|
@ -470,7 +487,8 @@ static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_vol_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
@ -484,7 +502,8 @@ static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_vol_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
@ -515,7 +534,8 @@ static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *
|
|
|
|
|
/*
|
|
|
|
|
* WM8770 mute control
|
|
|
|
|
*/
|
|
|
|
|
static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
|
|
|
|
|
static int wm_mute_info(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_info *uinfo) {
|
|
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
|
|
|
|
|
uinfo->count = kcontrol->private_value >> 8;
|
|
|
|
|
uinfo->value.integer.min = 0;
|
|
|
|
@ -523,7 +543,8 @@ static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_mute_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
@ -538,7 +559,8 @@ static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_mute_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
@ -553,9 +575,10 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value
|
|
|
|
|
if (ucontrol->value.integer.value[i] != val) {
|
|
|
|
|
spec->vol[ofs + i] &= ~WM_VOL_MUTE;
|
|
|
|
|
spec->vol[ofs + i] |=
|
|
|
|
|
ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
|
|
|
|
|
ucontrol->value.integer.value[i] ? 0 :
|
|
|
|
|
WM_VOL_MUTE;
|
|
|
|
|
wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
|
|
|
|
|
spec->master[i]);
|
|
|
|
|
spec->master[i]);
|
|
|
|
|
change = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -569,7 +592,8 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value
|
|
|
|
|
*/
|
|
|
|
|
#define wm_master_mute_info snd_ctl_boolean_stereo_info
|
|
|
|
|
|
|
|
|
|
static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_master_mute_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
@ -581,7 +605,8 @@ static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_master_mute_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
struct phase28_spec *spec = ice->spec;
|
|
|
|
@ -594,11 +619,12 @@ static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
|
|
|
|
|
int dac;
|
|
|
|
|
spec->master[i] &= ~WM_VOL_MUTE;
|
|
|
|
|
spec->master[i] |=
|
|
|
|
|
ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
|
|
|
|
|
ucontrol->value.integer.value[i] ? 0 :
|
|
|
|
|
WM_VOL_MUTE;
|
|
|
|
|
for (dac = 0; dac < ice->num_total_dacs; dac += 2)
|
|
|
|
|
wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
|
|
|
|
|
spec->vol[dac + i],
|
|
|
|
|
spec->master[i]);
|
|
|
|
|
spec->vol[dac + i],
|
|
|
|
|
spec->master[i]);
|
|
|
|
|
change = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -611,7 +637,8 @@ static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
|
|
|
|
|
#define PCM_0dB 0xff
|
|
|
|
|
#define PCM_RES 128 /* -64dB */
|
|
|
|
|
#define PCM_MIN (PCM_0dB - PCM_RES)
|
|
|
|
|
static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
{
|
|
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
|
|
|
|
uinfo->count = 1;
|
|
|
|
@ -620,7 +647,8 @@ static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_in
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
unsigned short val;
|
|
|
|
@ -633,7 +661,8 @@ static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
unsigned short ovol, nvol;
|
|
|
|
@ -647,7 +676,8 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
|
|
|
|
|
ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
|
|
|
|
|
if (ovol != nvol) {
|
|
|
|
|
wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
|
|
|
|
|
wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
|
|
|
|
|
/* update */
|
|
|
|
|
wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
|
|
|
|
|
change = 1;
|
|
|
|
|
}
|
|
|
|
|
snd_ice1712_restore_gpio_status(ice);
|
|
|
|
@ -659,18 +689,22 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
|
|
|
|
|
*/
|
|
|
|
|
#define phase28_deemp_info snd_ctl_boolean_mono_info
|
|
|
|
|
|
|
|
|
|
static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int phase28_deemp_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
|
|
|
|
|
ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) ==
|
|
|
|
|
0xf;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int phase28_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
int temp, temp2;
|
|
|
|
|
temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
|
|
|
|
|
temp = wm_get(ice, WM_DAC_CTRL2);
|
|
|
|
|
temp2 = temp;
|
|
|
|
|
if (ucontrol->value.integer.value[0])
|
|
|
|
|
temp |= 0xf;
|
|
|
|
|
else
|
|
|
|
@ -685,7 +719,8 @@ static int phase28_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
|
|
|
|
|
/*
|
|
|
|
|
* ADC Oversampling
|
|
|
|
|
*/
|
|
|
|
|
static int phase28_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
static int phase28_oversampling_info(struct snd_kcontrol *k,
|
|
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
|
|
{
|
|
|
|
|
static char *texts[2] = { "128x", "64x" };
|
|
|
|
|
|
|
|
|
@ -694,25 +729,31 @@ static int phase28_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem
|
|
|
|
|
uinfo->value.enumerated.items = 2;
|
|
|
|
|
|
|
|
|
|
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
|
|
|
|
|
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
|
|
|
|
|
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
|
|
|
|
|
uinfo->value.enumerated.item = uinfo->value.enumerated.items -
|
|
|
|
|
1;
|
|
|
|
|
strcpy(uinfo->value.enumerated.name,
|
|
|
|
|
texts[uinfo->value.enumerated.item]);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int phase28_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
static int phase28_oversampling_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) ==
|
|
|
|
|
0x8;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
|
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
{
|
|
|
|
|
int temp, temp2;
|
|
|
|
|
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
|
|
|
|
|
temp2 = temp = wm_get(ice, WM_MASTER);
|
|
|
|
|
temp = wm_get(ice, WM_MASTER);
|
|
|
|
|
temp2 = temp;
|
|
|
|
|
|
|
|
|
|
if (ucontrol->value.enumerated.item[0])
|
|
|
|
|
temp |= 0x8;
|
|
|
|
@ -885,13 +926,16 @@ static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
|
|
|
|
|
|
|
|
|
|
counts = ARRAY_SIZE(phase28_dac_controls);
|
|
|
|
|
for (i = 0; i < counts; i++) {
|
|
|
|
|
err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice));
|
|
|
|
|
err = snd_ctl_add(ice->card,
|
|
|
|
|
snd_ctl_new1(&phase28_dac_controls[i],
|
|
|
|
|
ice));
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
|
|
|
|
|
err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
|
|
|
|
|
err = snd_ctl_add(ice->card,
|
|
|
|
|
snd_ctl_new1(&wm_controls[i], ice));
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|