Commit 6dbc6caf authored by Yussuf Khalil's avatar Yussuf Khalil Committed by Takashi Iwai
Browse files

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: default avatarYussuf Khalil <dev@pp3345.net>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4fbd8d19
Loading
Loading
Loading
Loading
+102 −29
Original line number Diff line number Diff line
@@ -965,13 +965,32 @@ static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
	return 0;
}

static void wm8766_init(struct snd_ice1712 *ice)
{
	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;

/*
 * initialize the chip
 */
static int prodigy_hifi_init(struct snd_ice1712 *ice)
	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 wm_inits[] = {
	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;
}