These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / sound / soc / codecs / wm5102.c
index d476221..64637d1 100644 (file)
@@ -605,12 +605,56 @@ static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
                                regmap_write_async(regmap, patch[i].reg,
                                                   patch[i].def);
                break;
+       case SND_SOC_DAPM_PRE_PMD:
+               break;
+       default:
+               return 0;
+       }
+
+       return arizona_dvfs_sysclk_ev(w, kcontrol, event);
+}
+
+static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+       unsigned int v;
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v);
+               if (ret != 0) {
+                       dev_err(codec->dev,
+                               "Failed to read SYSCLK state: %d\n", ret);
+                       return -EIO;
+               }
+
+               v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT;
+
+               if (v >= 3) {
+                       ret = arizona_dvfs_up(codec, ARIZONA_DVFS_ADSP1_RQ);
+                       if (ret) {
+                               dev_err(codec->dev,
+                                       "Failed to raise DVFS: %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       case SND_SOC_DAPM_POST_PMD:
+               ret = arizona_dvfs_down(codec, ARIZONA_DVFS_ADSP1_RQ);
+               if (ret)
+                       dev_warn(codec->dev,
+                                "Failed to lower DVFS: %d\n", ret);
+               break;
 
        default:
                break;
        }
 
-       return 0;
+       return wm_adsp2_early_event(w, kcontrol, event);
 }
 
 static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol,
@@ -744,8 +788,7 @@ ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE),
 
-SND_SOC_BYTES("EQ1 Coefficients", ARIZONA_EQ1_3, 19),
-SOC_SINGLE("EQ1 Mode Switch", ARIZONA_EQ1_2, ARIZONA_EQ1_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ1 Coefficients", ARIZONA_EQ1_2),
 SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT,
@@ -757,8 +800,7 @@ SOC_SINGLE_TLV("EQ1 B4 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ1 B5 Volume", ARIZONA_EQ1_2, ARIZONA_EQ1_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ2 Coefficients", ARIZONA_EQ2_3, 19),
-SOC_SINGLE("EQ2 Mode Switch", ARIZONA_EQ2_2, ARIZONA_EQ2_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ2 Coefficients", ARIZONA_EQ2_2),
 SOC_SINGLE_TLV("EQ2 B1 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ2 B2 Volume", ARIZONA_EQ2_1, ARIZONA_EQ2_B2_GAIN_SHIFT,
@@ -770,8 +812,7 @@ SOC_SINGLE_TLV("EQ2 B4 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ2 B5 Volume", ARIZONA_EQ2_2, ARIZONA_EQ2_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ3 Coefficients", ARIZONA_EQ3_3, 19),
-SOC_SINGLE("EQ3 Mode Switch", ARIZONA_EQ3_2, ARIZONA_EQ3_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ3 Coefficients", ARIZONA_EQ3_2),
 SOC_SINGLE_TLV("EQ3 B1 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ3 B2 Volume", ARIZONA_EQ3_1, ARIZONA_EQ3_B2_GAIN_SHIFT,
@@ -783,8 +824,7 @@ SOC_SINGLE_TLV("EQ3 B4 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B4_GAIN_SHIFT,
 SOC_SINGLE_TLV("EQ3 B5 Volume", ARIZONA_EQ3_2, ARIZONA_EQ3_B5_GAIN_SHIFT,
               24, 0, eq_tlv),
 
-SND_SOC_BYTES("EQ4 Coefficients", ARIZONA_EQ4_3, 19),
-SOC_SINGLE("EQ4 Mode Switch", ARIZONA_EQ4_2, ARIZONA_EQ4_B1_MODE, 1, 0),
+ARIZONA_EQ_CONTROL("EQ4 Coefficients", ARIZONA_EQ4_2),
 SOC_SINGLE_TLV("EQ4 B1 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B1_GAIN_SHIFT,
               24, 0, eq_tlv),
 SOC_SINGLE_TLV("EQ4 B2 Volume", ARIZONA_EQ4_1, ARIZONA_EQ4_B2_GAIN_SHIFT,
@@ -807,10 +847,10 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
-SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1),
-SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1),
-SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1),
-SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1),
+ARIZONA_LHPF_CONTROL("LHPF1 Coefficients", ARIZONA_HPLPF1_2),
+ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),
+ARIZONA_LHPF_CONTROL("LHPF3 Coefficients", ARIZONA_HPLPF3_2),
+ARIZONA_LHPF_CONTROL("LHPF4 Coefficients", ARIZONA_HPLPF4_2),
 
 ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
@@ -1036,7 +1076,8 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
 
 static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
-                   0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU),
+                   0, wm5102_sysclk_ev,
+                   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
                    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
@@ -1367,7 +1408,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
 ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
 ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
 
-WM_ADSP2("DSP1", 0),
+WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev),
 
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
@@ -1827,27 +1868,40 @@ static struct snd_soc_dai_driver wm5102_dai[] = {
 
 static int wm5102_codec_probe(struct snd_soc_codec *codec)
 {
+       struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 2);
-       if (ret != 0)
+       ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec);
+       if (ret)
                return ret;
 
+       ret = snd_soc_add_codec_controls(codec,
+                                        arizona_adsp2_rate_controls, 1);
+       if (ret)
+               goto err_adsp2_codec_probe;
+
        arizona_init_spk(codec);
        arizona_init_gpio(codec);
 
-       snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
+       snd_soc_dapm_disable_pin(dapm, "HAPTICS");
 
-       priv->core.arizona->dapm = &codec->dapm;
+       priv->core.arizona->dapm = dapm;
 
        return 0;
+
+err_adsp2_codec_probe:
+       wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
+
+       return ret;
 }
 
 static int wm5102_codec_remove(struct snd_soc_codec *codec)
 {
        struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec);
 
+       wm_adsp2_codec_remove(&priv->core.adsp[0], codec);
+
        priv->core.arizona->dapm = NULL;
 
        return 0;
@@ -1909,6 +1963,8 @@ static int wm5102_probe(struct platform_device *pdev)
        wm5102->core.arizona = arizona;
        wm5102->core.num_inputs = 6;
 
+       arizona_init_dvfs(&wm5102->core);
+
        wm5102->core.adsp[0].part = "wm5102";
        wm5102->core.adsp[0].num = 1;
        wm5102->core.adsp[0].type = WMFW_ADSP2;
@@ -1918,7 +1974,7 @@ static int wm5102_probe(struct platform_device *pdev)
        wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
        wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
 
-       ret = wm_adsp2_init(&wm5102->core.adsp[0], true);
+       ret = wm_adsp2_init(&wm5102->core.adsp[0]);
        if (ret != 0)
                return ret;