ALSA: ice1724: Fix resume issues with Prodigy 7.1 HiFi

There are two issues after resuming from suspend on the
Audiotrak Prodigy 7.1 HiFi:
 - the output volume is set to 100%
 - microphone input isn't working anymore

This patch fixes these issues by reinitializing both codecs of the device
and restoring the previous volumes during resume.

Signed-off-by: Yussuf Khalil <dev@pp3345.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Yussuf Khalil 2017-11-25 23:31:08 +01:00 committed by Takashi Iwai
parent 4fbd8d194f
commit 6dbc6caf66
1 changed files with 103 additions and 30 deletions

View File

@ -965,13 +965,32 @@ static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
return 0;
}
/*
* initialize the chip
*/
static int prodigy_hifi_init(struct snd_ice1712 *ice)
static void wm8766_init(struct snd_ice1712 *ice)
{
static unsigned short wm_inits[] = {
static unsigned short wm8766_inits[] = {
WM8766_RESET, 0x0000,
WM8766_DAC_CTRL, 0x0120,
WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */
WM8766_DAC_CTRL2, 0x0001,
WM8766_DAC_CTRL3, 0x0080,
WM8766_LDA1, 0x0100,
WM8766_LDA2, 0x0100,
WM8766_LDA3, 0x0100,
WM8766_RDA1, 0x0100,
WM8766_RDA2, 0x0100,
WM8766_RDA3, 0x0100,
WM8766_MUTE1, 0x0000,
WM8766_MUTE2, 0x0000,
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2)
wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i + 1]);
}
static void wm8776_init(struct snd_ice1712 *ice)
{
static unsigned short wm8776_inits[] = {
/* These come first to reduce init pop noise */
WM_ADC_MUX, 0x0003, /* ADC mute */
/* 0x00c0 replaced by 0x0003 */
@ -982,7 +1001,76 @@ static int prodigy_hifi_init(struct snd_ice1712 *ice)
WM_POWERDOWN, 0x0008, /* All power-up except HP */
WM_RESET, 0x0000, /* reset */
};
static unsigned short wm_inits2[] = {
unsigned int i;
for (i = 0; i < ARRAY_SIZE(wm8776_inits); i += 2)
wm_put(ice, wm8776_inits[i], wm8776_inits[i + 1]);
}
#ifdef CONFIG_PM_SLEEP
static int prodigy_hifi_resume(struct snd_ice1712 *ice)
{
static unsigned short wm8776_reinit_registers[] = {
WM_MASTER_CTRL,
WM_DAC_INT,
WM_ADC_INT,
WM_OUT_MUX,
WM_HP_ATTEN_L,
WM_HP_ATTEN_R,
WM_PHASE_SWAP,
WM_DAC_CTRL2,
WM_ADC_ATTEN_L,
WM_ADC_ATTEN_R,
WM_ALC_CTRL1,
WM_ALC_CTRL2,
WM_ALC_CTRL3,
WM_NOISE_GATE,
WM_ADC_MUX,
/* no DAC attenuation here */
};
struct prodigy_hifi_spec *spec = ice->spec;
int i, ch;
mutex_lock(&ice->gpio_mutex);
/* reinitialize WM8776 and re-apply old register values */
wm8776_init(ice);
schedule_timeout_uninterruptible(1);
for (i = 0; i < ARRAY_SIZE(wm8776_reinit_registers); i++)
wm_put(ice, wm8776_reinit_registers[i],
wm_get(ice, wm8776_reinit_registers[i]));
/* reinitialize WM8766 and re-apply volumes for all DACs */
wm8766_init(ice);
for (ch = 0; ch < 2; ch++) {
wm_set_vol(ice, WM_DAC_ATTEN_L + ch,
spec->vol[2 + ch], spec->master[ch]);
wm8766_set_vol(ice, WM8766_LDA1 + ch,
spec->vol[0 + ch], spec->master[ch]);
wm8766_set_vol(ice, WM8766_LDA2 + ch,
spec->vol[4 + ch], spec->master[ch]);
wm8766_set_vol(ice, WM8766_LDA3 + ch,
spec->vol[6 + ch], spec->master[ch]);
}
/* unmute WM8776 DAC */
wm_put(ice, WM_DAC_MUTE, 0x00);
wm_put(ice, WM_DAC_CTRL1, 0x90);
mutex_unlock(&ice->gpio_mutex);
return 0;
}
#endif
/*
* initialize the chip
*/
static int prodigy_hifi_init(struct snd_ice1712 *ice)
{
static unsigned short wm8776_defaults[] = {
WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */
WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */
WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */
@ -1010,22 +1098,6 @@ static int prodigy_hifi_init(struct snd_ice1712 *ice)
WM_DAC_MUTE, 0x0000, /* DAC unmute */
WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */
};
static unsigned short wm8766_inits[] = {
WM8766_RESET, 0x0000,
WM8766_DAC_CTRL, 0x0120,
WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */
WM8766_DAC_CTRL2, 0x0001,
WM8766_DAC_CTRL3, 0x0080,
WM8766_LDA1, 0x0100,
WM8766_LDA2, 0x0100,
WM8766_LDA3, 0x0100,
WM8766_RDA1, 0x0100,
WM8766_RDA2, 0x0100,
WM8766_RDA3, 0x0100,
WM8766_MUTE1, 0x0000,
WM8766_MUTE2, 0x0000,
};
struct prodigy_hifi_spec *spec;
unsigned int i;
@ -1052,16 +1124,17 @@ static int prodigy_hifi_init(struct snd_ice1712 *ice)
ice->spec = spec;
/* initialize WM8776 codec */
for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
wm_put(ice, wm_inits[i], wm_inits[i+1]);
wm8776_init(ice);
schedule_timeout_uninterruptible(1);
for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2)
wm_put(ice, wm_inits2[i], wm_inits2[i+1]);
for (i = 0; i < ARRAY_SIZE(wm8776_defaults); i += 2)
wm_put(ice, wm8776_defaults[i], wm8776_defaults[i + 1]);
/* initialize WM8766 codec */
for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2)
wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i+1]);
wm8766_init(ice);
#ifdef CONFIG_PM_SLEEP
ice->pm_resume = &prodigy_hifi_resume;
ice->pm_suspend_enabled = 1;
#endif
return 0;
}