Merge branch 'asoc-5.4' into asoc-5.5
authorMark Brown <broonie@kernel.org>
Wed, 2 Oct 2019 11:50:40 +0000 (12:50 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 2 Oct 2019 11:50:40 +0000 (12:50 +0100)
1  2 
sound/soc/codecs/wm8994.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/bdw.c
sound/soc/sof/intel/byt.c

index b633093afb9d7b845c0c68dc81f01af9dc7e8842,d5fb7f5dd551cb834ad77ae9b99ca453d7264008..15ce64a48a87438672678f128be57f05f91eaa6d
@@@ -167,12 -167,12 +167,12 @@@ static int configure_aif_clock(struct s
  
        switch (wm8994->sysclk[aif]) {
        case WM8994_SYSCLK_MCLK1:
 -              rate = wm8994->mclk[0];
 +              rate = wm8994->mclk_rate[0];
                break;
  
        case WM8994_SYSCLK_MCLK2:
                reg1 |= 0x8;
 -              rate = wm8994->mclk[1];
 +              rate = wm8994->mclk_rate[1];
                break;
  
        case WM8994_SYSCLK_FLL1:
@@@ -533,13 -533,10 +533,10 @@@ static SOC_ENUM_SINGLE_DECL(dac_osr
  static SOC_ENUM_SINGLE_DECL(adc_osr,
                            WM8994_OVERSAMPLING, 1, osr_text);
  
- static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+ static const struct snd_kcontrol_new wm8994_common_snd_controls[] = {
  SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
                 WM8994_AIF1_ADC1_RIGHT_VOLUME,
                 1, 119, 0, digital_tlv),
- SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
-                WM8994_AIF1_ADC2_RIGHT_VOLUME,
-                1, 119, 0, digital_tlv),
  SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME,
                 WM8994_AIF2_ADC_RIGHT_VOLUME,
                 1, 119, 0, digital_tlv),
@@@ -556,8 -553,6 +553,6 @@@ SOC_ENUM("AIF2DACR Source", aif2dacr_sr
  
  SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME,
                 WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
- SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
-                WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
  SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8994_AIF2_DAC_LEFT_VOLUME,
                 WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
  
@@@ -565,17 -560,12 +560,12 @@@ SOC_SINGLE_TLV("AIF1 Boost Volume", WM8
  SOC_SINGLE_TLV("AIF2 Boost Volume", WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv),
  
  SOC_SINGLE("AIF1DAC1 EQ Switch", WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0),
- SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
  SOC_SINGLE("AIF2 EQ Switch", WM8994_AIF2_EQ_GAINS_1, 0, 1, 0),
  
  WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch", WM8994_AIF1_DRC1_1, 2),
  WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch", WM8994_AIF1_DRC1_1, 1),
  WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch", WM8994_AIF1_DRC1_1, 0),
  
- WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
- WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
- WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
  WM8994_DRC_SWITCH("AIF2DAC DRC Switch", WM8994_AIF2_DRC_1, 2),
  WM8994_DRC_SWITCH("AIF2ADCL DRC Switch", WM8994_AIF2_DRC_1, 1),
  WM8994_DRC_SWITCH("AIF2ADCR DRC Switch", WM8994_AIF2_DRC_1, 0),
@@@ -594,9 -584,6 +584,6 @@@ SOC_SINGLE("Sidetone HPF Switch", WM899
  SOC_ENUM("AIF1ADC1 HPF Mode", aif1adc1_hpf),
  SOC_DOUBLE("AIF1ADC1 HPF Switch", WM8994_AIF1_ADC1_FILTERS, 12, 11, 1, 0),
  
- SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
- SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
  SOC_ENUM("AIF2ADC HPF Mode", aif2adc_hpf),
  SOC_DOUBLE("AIF2ADC HPF Switch", WM8994_AIF2_ADC_FILTERS, 12, 11, 1, 0),
  
@@@ -637,6 -624,24 +624,24 @@@ SOC_SINGLE("AIF2DAC 3D Stereo Switch", 
           8, 1, 0),
  };
  
+ /* Controls not available on WM1811 */
+ static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
+                WM8994_AIF1_ADC2_RIGHT_VOLUME,
+                1, 119, 0, digital_tlv),
+ SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
+                WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
+ SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
+ WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
+ WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
+ WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
+ SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
+ SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
+ };
  static const struct snd_kcontrol_new wm8994_eq_controls[] = {
  SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0,
               eq_tlv),
@@@ -1033,45 -1038,6 +1038,45 @@@ static bool wm8994_check_class_w_digita
        return true;
  }
  
 +static int aif_mclk_set(struct snd_soc_component *component, int aif, bool enable)
 +{
 +      struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 +      unsigned int offset, val, clk_idx;
 +      int ret;
 +
 +      if (aif)
 +              offset = 4;
 +      else
 +              offset = 0;
 +
 +      val = snd_soc_component_read32(component, WM8994_AIF1_CLOCKING_1 + offset);
 +      val &= WM8994_AIF1CLK_SRC_MASK;
 +
 +      switch (val) {
 +      case 0:
 +              clk_idx = WM8994_MCLK1;
 +              break;
 +      case 1:
 +              clk_idx = WM8994_MCLK2;
 +              break;
 +      default:
 +              return 0;
 +      }
 +
 +      if (enable) {
 +              ret = clk_prepare_enable(wm8994->mclk[clk_idx].clk);
 +              if (ret < 0) {
 +                      dev_err(component->dev, "Failed to enable MCLK%d\n",
 +                              clk_idx);
 +                      return ret;
 +              }
 +      } else {
 +              clk_disable_unprepare(wm8994->mclk[clk_idx].clk);
 +      }
 +
 +      return 0;
 +}
 +
  static int aif1clk_ev(struct snd_soc_dapm_widget *w,
                      struct snd_kcontrol *kcontrol, int event)
  {
        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
        struct wm8994 *control = wm8994->wm8994;
        int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
 -      int i;
 +      int ret, i;
        int dac;
        int adc;
        int val;
  
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
 +              ret = aif_mclk_set(component, 0, true);
 +              if (ret < 0)
 +                      return ret;
 +
                /* Don't enable timeslot 2 if not in use */
                if (wm8994->channels[0] <= 2)
                        mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
                break;
        }
  
 +      switch (event) {
 +      case SND_SOC_DAPM_POST_PMD:
 +              aif_mclk_set(component, 0, false);
 +              break;
 +      }
 +
        return 0;
  }
  
@@@ -1184,17 -1140,13 +1189,17 @@@ static int aif2clk_ev(struct snd_soc_da
                      struct snd_kcontrol *kcontrol, int event)
  {
        struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 -      int i;
 +      int ret, i;
        int dac;
        int adc;
        int val;
  
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
 +              ret = aif_mclk_set(component, 1, true);
 +              if (ret < 0)
 +                      return ret;
 +
                val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_1);
                if ((val & WM8994_AIF2ADCL_SRC) &&
                    (val & WM8994_AIF2ADCR_SRC))
                break;
        }
  
 +      switch (event) {
 +      case SND_SOC_DAPM_POST_PMD:
 +              aif_mclk_set(component, 1, false);
 +              break;
 +      }
 +
        return 0;
  }
  
@@@ -1677,10 -1623,10 +1682,10 @@@ SND_SOC_DAPM_POST("Late Disable PGA", l
  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_POST_PMU |
 -                  SND_SOC_DAPM_PRE_PMD),
 +                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
  SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev,
                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 -                  SND_SOC_DAPM_PRE_PMD),
 +                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_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)),
@@@ -2195,7 -2141,6 +2200,7 @@@ static int _wm8994_set_fll(struct snd_s
        u16 reg, clk1, aif_reg, aif_src;
        unsigned long timeout;
        bool was_enabled;
 +      struct clk *mclk;
  
        switch (id) {
        case WM8994_FLL1:
        snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_1 + reg_offset,
                            WM8994_FLL1_ENA, 0);
  
 +      /* Disable MCLK if needed before we possibly change to new clock parent */
 +      if (was_enabled) {
 +              reg = snd_soc_component_read32(component, WM8994_FLL1_CONTROL_5
 +                                                      + reg_offset);
 +              reg = ((reg & WM8994_FLL1_REFCLK_SRC_MASK)
 +                      >> WM8994_FLL1_REFCLK_SRC_SHIFT) + 1;
 +
 +              switch (reg) {
 +              case WM8994_FLL_SRC_MCLK1:
 +                      mclk = wm8994->mclk[WM8994_MCLK1].clk;
 +                      break;
 +              case WM8994_FLL_SRC_MCLK2:
 +                      mclk = wm8994->mclk[WM8994_MCLK2].clk;
 +                      break;
 +              default:
 +                      mclk = NULL;
 +              }
 +
 +              clk_disable_unprepare(mclk);
 +      }
 +
        if (wm8994->fll_byp && src == WM8994_FLL_SRC_BCLK &&
            freq_in == freq_out && freq_out) {
                dev_dbg(component->dev, "Bypassing FLL%d\n", id + 1);
        /* Clear any pending completion from a previous failure */
        try_wait_for_completion(&wm8994->fll_locked[id]);
  
 +      switch (src) {
 +      case WM8994_FLL_SRC_MCLK1:
 +              mclk = wm8994->mclk[WM8994_MCLK1].clk;
 +              break;
 +      case WM8994_FLL_SRC_MCLK2:
 +              mclk = wm8994->mclk[WM8994_MCLK2].clk;
 +              break;
 +      default:
 +              mclk = NULL;
 +      }
 +
        /* Enable (with fractional mode if required) */
        if (freq_out) {
 +              ret = clk_prepare_enable(mclk);
 +              if (ret < 0) {
 +                      dev_err(component->dev, "Failed to enable MCLK for FLL%d\n",
 +                              id + 1);
 +                      return ret;
 +              }
 +
                /* Enable VMID if we need it */
                if (!was_enabled) {
 +
                        active_reference(component);
  
                        switch (control->type) {
@@@ -2467,29 -2372,12 +2472,29 @@@ static int wm8994_set_fll(struct snd_so
        return _wm8994_set_fll(dai->component, id, src, freq_in, freq_out);
  }
  
 +static int wm8994_set_mclk_rate(struct wm8994_priv *wm8994, unsigned int id,
 +                              unsigned int *freq)
 +{
 +      int ret;
 +
 +      if (!wm8994->mclk[id].clk || *freq == wm8994->mclk_rate[id])
 +              return 0;
 +
 +      ret = clk_set_rate(wm8994->mclk[id].clk, *freq);
 +      if (ret < 0)
 +              return ret;
 +
 +      *freq = clk_get_rate(wm8994->mclk[id].clk);
 +
 +      return 0;
 +}
 +
  static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
                int clk_id, unsigned int freq, int dir)
  {
        struct snd_soc_component *component = dai->component;
        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
 -      int i;
 +      int ret, i;
  
        switch (dai->id) {
        case 1:
        switch (clk_id) {
        case WM8994_SYSCLK_MCLK1:
                wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1;
 -              wm8994->mclk[0] = freq;
 +
 +              ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
 +              if (ret < 0)
 +                      return ret;
 +
 +              wm8994->mclk_rate[0] = freq;
                dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n",
                        dai->id, freq);
                break;
        case WM8994_SYSCLK_MCLK2:
                /* TODO: Set GPIO AF */
                wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2;
 -              wm8994->mclk[1] = freq;
 +
 +              ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
 +              if (ret < 0)
 +                      return ret;
 +
 +              wm8994->mclk_rate[1] = freq;
                dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n",
                        dai->id, freq);
                break;
@@@ -4385,13 -4263,15 +4390,15 @@@ static int wm8994_component_probe(struc
        wm8994_handle_pdata(wm8994);
  
        wm_hubs_add_analogue_controls(component);
-       snd_soc_add_component_controls(component, wm8994_snd_controls,
-                            ARRAY_SIZE(wm8994_snd_controls));
+       snd_soc_add_component_controls(component, wm8994_common_snd_controls,
+                                      ARRAY_SIZE(wm8994_common_snd_controls));
        snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
                                  ARRAY_SIZE(wm8994_dapm_widgets));
  
        switch (control->type) {
        case WM8994:
+               snd_soc_add_component_controls(component, wm8994_snd_controls,
+                                              ARRAY_SIZE(wm8994_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
                                          ARRAY_SIZE(wm8994_specific_dapm_widgets));
                if (control->revision < 4) {
                }
                break;
        case WM8958:
+               snd_soc_add_component_controls(component, wm8994_snd_controls,
+                                              ARRAY_SIZE(wm8994_snd_controls));
                snd_soc_add_component_controls(component, wm8958_snd_controls,
-                                    ARRAY_SIZE(wm8958_snd_controls));
+                                              ARRAY_SIZE(wm8958_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
                                          ARRAY_SIZE(wm8958_dapm_widgets));
                if (control->revision < 1) {
@@@ -4574,7 -4456,6 +4583,7 @@@ static const struct snd_soc_component_d
  static int wm8994_probe(struct platform_device *pdev)
  {
        struct wm8994_priv *wm8994;
 +      int ret;
  
        wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
                              GFP_KERNEL);
  
        wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
  
 +      wm8994->mclk[WM8994_MCLK1].id = "MCLK1";
 +      wm8994->mclk[WM8994_MCLK2].id = "MCLK2";
 +
 +      ret = devm_clk_bulk_get_optional(pdev->dev.parent, ARRAY_SIZE(wm8994->mclk),
 +                                       wm8994->mclk);
 +      if (ret < 0) {
 +              dev_err(&pdev->dev, "Failed to get clocks: %d\n", ret);
 +              return ret;
 +      }
 +
        pm_runtime_enable(&pdev->dev);
        pm_runtime_idle(&pdev->dev);
  
diff --combined sound/soc/soc-pcm.c
index e7a04c892817ba669726949260d7164d5b43fa23,a1b99ac57d9eeb48ac57723533abe70cccbc1e74..66910500e3b69e96fd0132ac6132051d1861194e
@@@ -1047,7 -1047,7 +1047,7 @@@ static int soc_pcm_hw_free(struct snd_p
        return 0;
  }
  
 -static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 +static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd)
  {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_component *component;
        struct snd_soc_dai *codec_dai;
        int i, ret;
  
 -      for_each_rtd_codec_dai(rtd, i, codec_dai) {
 -              ret = snd_soc_dai_trigger(codec_dai, substream, cmd);
 +      if (rtd->dai_link->ops->trigger) {
 +              ret = rtd->dai_link->ops->trigger(substream, cmd);
                if (ret < 0)
                        return ret;
        }
                        return ret;
        }
  
-       snd_soc_dai_trigger(cpu_dai, substream, cmd);
+       ret = snd_soc_dai_trigger(cpu_dai, substream, cmd);
        if (ret < 0)
                return ret;
  
 +      for_each_rtd_codec_dai(rtd, i, codec_dai) {
 +              ret = snd_soc_dai_trigger(codec_dai, substream, cmd);
 +              if (ret < 0)
 +                      return ret;
 +      }
 +
 +      return 0;
 +}
 +
 +static int soc_pcm_trigger_stop(struct snd_pcm_substream *substream, int cmd)
 +{
 +      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 +      struct snd_soc_component *component;
 +      struct snd_soc_rtdcom_list *rtdcom;
 +      struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 +      struct snd_soc_dai *codec_dai;
 +      int i, ret;
 +
 +      for_each_rtd_codec_dai(rtd, i, codec_dai) {
 +              ret = snd_soc_dai_trigger(codec_dai, substream, cmd);
 +              if (ret < 0)
 +                      return ret;
 +      }
 +
 +      ret = snd_soc_dai_trigger(cpu_dai, substream, cmd);
 +      if (ret < 0)
 +              return ret;
 +
 +      for_each_rtdcom(rtd, rtdcom) {
 +              component = rtdcom->component;
 +
 +              ret = snd_soc_component_trigger(component, substream, cmd);
 +              if (ret < 0)
 +                      return ret;
 +      }
 +
        if (rtd->dai_link->ops->trigger) {
                ret = rtd->dai_link->ops->trigger(substream, cmd);
                if (ret < 0)
        return 0;
  }
  
 +static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 +{
 +      int ret;
 +
 +      switch (cmd) {
 +      case SNDRV_PCM_TRIGGER_START:
 +      case SNDRV_PCM_TRIGGER_RESUME:
 +      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 +              ret = soc_pcm_trigger_start(substream, cmd);
 +              break;
 +      case SNDRV_PCM_TRIGGER_STOP:
 +      case SNDRV_PCM_TRIGGER_SUSPEND:
 +      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 +              ret = soc_pcm_trigger_stop(substream, cmd);
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      return ret;
 +}
 +
  static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
                                   int cmd)
  {
                        return ret;
        }
  
-       snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd);
+       ret = snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd);
        if (ret < 0)
                return ret;
  
diff --combined sound/soc/soc-topology.c
index aa9a1fca46fa7832271ff0d3919959f94dfaa0a4,c25939c5611b917ee9462cc50a473a40d8e59291..0fd032914a318b39d46f89ac8af1435de11ebba1
@@@ -80,6 -80,12 +80,6 @@@ struct soc_tplg 
  
  static int soc_tplg_process_headers(struct soc_tplg *tplg);
  static void soc_tplg_complete(struct soc_tplg *tplg);
 -struct snd_soc_dapm_widget *
 -snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
 -                       const struct snd_soc_dapm_widget *widget);
 -struct snd_soc_dapm_widget *
 -snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 -                       const struct snd_soc_dapm_widget *widget);
  static void soc_tplg_denum_remove_texts(struct soc_enum *se);
  static void soc_tplg_denum_remove_values(struct soc_enum *se);
  
@@@ -1582,7 -1588,7 +1582,7 @@@ static int soc_tplg_dapm_widget_create(
  
        /* map user to kernel widget ID */
        template.id = get_widget_id(le32_to_cpu(w->id));
-       if (template.id < 0)
+       if ((int)template.id < 0)
                return template.id;
  
        /* strings are allocated here, but used and freed by the widget */
index 170c74dc13b1995a768479c2ccb3e4748ed95d9e,80e2826fb447b28524268ccbf598f5f73e75abd7..f395d063887656715219e6044db5518b163511e0
@@@ -37,6 -37,7 +37,7 @@@
  #define MBOX_SIZE       0x1000
  #define MBOX_DUMP_SIZE 0x30
  #define EXCEPT_OFFSET 0x800
+ #define EXCEPT_MAX_HDR_SIZE   0x400
  
  /* DSP peripherals */
  #define DMAC0_OFFSET    0xFE000
@@@ -228,6 -229,11 +229,11 @@@ static void bdw_get_registers(struct sn
        /* note: variable AR register array is not read */
  
        /* then get panic info */
+       if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+               dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+                       xoops->arch_hdr.totalsize);
+               return;
+       }
        offset += xoops->arch_hdr.totalsize;
        sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
  
@@@ -241,7 -247,7 +247,7 @@@ static void bdw_dump(struct snd_sof_de
        struct sof_ipc_dsp_oops_xtensa xoops;
        struct sof_ipc_panic_info panic_info;
        u32 stack[BDW_STACK_DUMP_SIZE];
 -      u32 status, panic;
 +      u32 status, panic, imrx, imrd;
  
        /* now try generic SOF status messages */
        status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
                          BDW_STACK_DUMP_SIZE);
        snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
                           BDW_STACK_DUMP_SIZE);
 +
 +      /* provide some context for firmware debug */
 +      imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX);
 +      imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD);
 +      dev_err(sdev->dev,
 +              "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
 +              panic & SHIM_IPCX_BUSY ? "yes" : "no",
 +              panic & SHIM_IPCX_DONE ? "yes" : "no", panic);
 +      dev_err(sdev->dev,
 +              "error: mask host: pending %s complete %s raw 0x%8.8x\n",
 +              imrx & SHIM_IMRX_BUSY ? "yes" : "no",
 +              imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx);
 +      dev_err(sdev->dev,
 +              "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
 +              status & SHIM_IPCD_BUSY ? "yes" : "no",
 +              status & SHIM_IPCD_DONE ? "yes" : "no", status);
 +      dev_err(sdev->dev,
 +              "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
 +              imrd & SHIM_IMRD_BUSY ? "yes" : "no",
 +              imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd);
  }
  
  /*
@@@ -471,6 -457,7 +477,7 @@@ static int bdw_probe(struct snd_sof_de
        /* TODO: add offsets */
        sdev->mmio_bar = BDW_DSP_BAR;
        sdev->mailbox_bar = BDW_DSP_BAR;
+       sdev->dsp_oops_offset = MBOX_OFFSET;
  
        /* PCI base */
        mmio = platform_get_resource(pdev, IORESOURCE_MEM,
index ecbc9c79bcad35cc3637cbd6b0f536c02a24384f,a1e514f7173952fe899923bd9ffda4009753674f..b2597ecfdc1caaf12a8619e4edd1a8d2164b8a6e
@@@ -28,6 -28,7 +28,7 @@@
  #define MBOX_OFFSET           0x144000
  #define MBOX_SIZE             0x1000
  #define EXCEPT_OFFSET         0x800
+ #define EXCEPT_MAX_HDR_SIZE   0x400
  
  /* DSP peripherals */
  #define DMAC0_OFFSET          0x098000
@@@ -126,6 -127,11 +127,11 @@@ static void byt_get_registers(struct sn
        /* note: variable AR register array is not read */
  
        /* then get panic info */
+       if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+               dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+                       xoops->arch_hdr.totalsize);
+               return;
+       }
        offset += xoops->arch_hdr.totalsize;
        sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
  
@@@ -139,7 -145,7 +145,7 @@@ static void byt_dump(struct snd_sof_de
        struct sof_ipc_dsp_oops_xtensa xoops;
        struct sof_ipc_panic_info panic_info;
        u32 stack[BYT_STACK_DUMP_SIZE];
 -      u32 status, panic;
 +      u32 status, panic, imrd, imrx;
  
        /* now try generic SOF status messages */
        status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD);
                          BYT_STACK_DUMP_SIZE);
        snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
                           BYT_STACK_DUMP_SIZE);
 +
 +      /* provide some context for firmware debug */
 +      imrx = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRX);
 +      imrd = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRD);
 +      dev_err(sdev->dev,
 +              "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
 +              panic & SHIM_IPCX_BUSY ? "yes" : "no",
 +              panic & SHIM_IPCX_DONE ? "yes" : "no", panic);
 +      dev_err(sdev->dev,
 +              "error: mask host: pending %s complete %s raw 0x%8.8x\n",
 +              imrx & SHIM_IMRX_BUSY ? "yes" : "no",
 +              imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx);
 +      dev_err(sdev->dev,
 +              "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
 +              status & SHIM_IPCD_BUSY ? "yes" : "no",
 +              status & SHIM_IPCD_DONE ? "yes" : "no", status);
 +      dev_err(sdev->dev,
 +              "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
 +              imrd & SHIM_IMRD_BUSY ? "yes" : "no",
 +              imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd);
 +
  }
  
  /*