diff options
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
| -rw-r--r-- | sound/soc/codecs/wm8994.c | 108 | 
1 files changed, 66 insertions, 42 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 993639d694c..1436b6ce74d 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -46,6 +46,39 @@  #define WM8994_NUM_DRC 3  #define WM8994_NUM_EQ  3 +static struct { +	unsigned int reg; +	unsigned int mask; +} wm8994_vu_bits[] = { +	{ WM8994_LEFT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, +	{ WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, +	{ WM8994_LEFT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, +	{ WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, +	{ WM8994_SPEAKER_VOLUME_LEFT, WM8994_SPKOUT_VU }, +	{ WM8994_SPEAKER_VOLUME_RIGHT, WM8994_SPKOUT_VU }, +	{ WM8994_LEFT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, +	{ WM8994_RIGHT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, +	{ WM8994_LEFT_OPGA_VOLUME, WM8994_MIXOUT_VU }, +	{ WM8994_RIGHT_OPGA_VOLUME, WM8994_MIXOUT_VU }, + +	{ WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1DAC1_VU }, +	{ WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU }, +	{ WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU }, +	{ WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU }, +	{ WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2DAC_VU }, +	{ WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU }, +	{ WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1ADC1_VU }, +	{ WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU }, +	{ WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU }, +	{ WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, +	{ WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2ADC_VU }, +	{ WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, +	{ WM8994_DAC1_LEFT_VOLUME, WM8994_DAC1_VU }, +	{ WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU }, +	{ WM8994_DAC2_LEFT_VOLUME, WM8994_DAC2_VU }, +	{ WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU }, +}; +  static int wm8994_drc_base[] = {  	WM8994_AIF1_DRC1_1,  	WM8994_AIF1_DRC2_1, @@ -694,9 +727,6 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)  	if (!wm8994->jackdet || !wm8994->jack_cb)  		return; -	if (!wm8994->jackdet || !wm8994->jack_cb) -		return; -  	if (wm8994->active_refcount)  		mode = WM1811_JACKDET_MODE_AUDIO; @@ -989,6 +1019,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,  	struct snd_soc_codec *codec = w->codec;  	struct wm8994 *control = codec->control_data;  	int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; +	int i;  	int dac;  	int adc;  	int val; @@ -1047,6 +1078,13 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,  				    WM8994_AIF1DAC2L_ENA);  		break; +	case SND_SOC_DAPM_POST_PMU: +		for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) +			snd_soc_write(codec, wm8994_vu_bits[i].reg, +				      snd_soc_read(codec, +						   wm8994_vu_bits[i].reg)); +		break; +  	case SND_SOC_DAPM_PRE_PMD:  	case SND_SOC_DAPM_POST_PMD:  		snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1072,6 +1110,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,  		      struct snd_kcontrol *kcontrol, int event)  {  	struct snd_soc_codec *codec = w->codec; +	int i;  	int dac;  	int adc;  	int val; @@ -1122,6 +1161,13 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,  				    WM8994_AIF2DACR_ENA);  		break; +	case SND_SOC_DAPM_POST_PMU: +		for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) +			snd_soc_write(codec, wm8994_vu_bits[i].reg, +				      snd_soc_read(codec, +						   wm8994_vu_bits[i].reg)); +		break; +  	case SND_SOC_DAPM_PRE_PMD:  	case SND_SOC_DAPM_POST_PMD:  		snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1190,17 +1236,19 @@ static int late_enable_ev(struct snd_soc_dapm_widget *w,  	switch (event) {  	case SND_SOC_DAPM_PRE_PMU:  		if (wm8994->aif1clk_enable) { -			aif1clk_ev(w, kcontrol, event); +			aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU);  			snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,  					    WM8994_AIF1CLK_ENA_MASK,  					    WM8994_AIF1CLK_ENA); +			aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU);  			wm8994->aif1clk_enable = 0;  		}  		if (wm8994->aif2clk_enable) { -			aif2clk_ev(w, kcontrol, event); +			aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU);  			snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1,  					    WM8994_AIF2CLK_ENA_MASK,  					    WM8994_AIF2CLK_ENA); +			aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU);  			wm8994->aif2clk_enable = 0;  		}  		break; @@ -1221,15 +1269,17 @@ static int late_disable_ev(struct snd_soc_dapm_widget *w,  	switch (event) {  	case SND_SOC_DAPM_POST_PMD:  		if (wm8994->aif1clk_disable) { +			aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD);  			snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1,  					    WM8994_AIF1CLK_ENA_MASK, 0); -			aif1clk_ev(w, kcontrol, event); +			aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD);  			wm8994->aif1clk_disable = 0;  		}  		if (wm8994->aif2clk_disable) { +			aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD);  			snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1,  					    WM8994_AIF2CLK_ENA_MASK, 0); -			aif2clk_ev(w, kcontrol, event); +			aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD);  			wm8994->aif2clk_disable = 0;  		}  		break; @@ -1527,9 +1577,11 @@ SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev)  static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = {  SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, -		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), +		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		    SND_SOC_DAPM_PRE_PMD),  SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, -		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), +		    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | +		    SND_SOC_DAPM_PRE_PMD),  SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),  SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,  		   left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), @@ -3879,39 +3931,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)  	pm_runtime_put(codec->dev); -	/* Latch volume updates (right only; we always do left then right). */ -	snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, -			    WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); -	snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, -			    WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); -	snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME, -			    WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); -	snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME, -			    WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); -	snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME, -			    WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); -	snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME, -			    WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); -	snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, -			    WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); -	snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, -			    WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); -	snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME, -			    WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); -	snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME, -			    WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); -	snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME, -			    WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); -	snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME, -			    WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); -	snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME, -			    WM8994_DAC1_VU, WM8994_DAC1_VU); -	snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME, -			    WM8994_DAC1_VU, WM8994_DAC1_VU); -	snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME, -			    WM8994_DAC2_VU, WM8994_DAC2_VU); -	snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME, -			    WM8994_DAC2_VU, WM8994_DAC2_VU); +	/* Latch volume update bits */ +	for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) +		snd_soc_update_bits(codec, wm8994_vu_bits[i].reg, +				    wm8994_vu_bits[i].mask, +				    wm8994_vu_bits[i].mask);  	/* Set the low bit of the 3D stereo depth so TLV matches */  	snd_soc_update_bits(codec, WM8994_AIF1_DAC1_FILTERS_2,  |