|
@@ -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,
|
|
@@ -989,6 +1022,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 +1081,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 +1113,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 +1164,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 +1239,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 +1272,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 +1580,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 +3934,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,
|