ASoC: adau17x1: Handling of DSP_RUN register during fw setup
authorDanny Smith <dannys@axis.com>
Mon, 9 Apr 2018 13:13:35 +0000 (15:13 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 13 Apr 2018 10:39:16 +0000 (11:39 +0100)
DSP_RUN needs to be disabled during firmware write otherwise
we can end up with undefined behavior if writing to a dsp which
is already running firmware.

Signed-off-by: Danny Smith <dannys@axis.com>
Signed-off-by: Robert Rosengren <robert.rosengren@axis.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/adau17x1.c
sound/soc/codecs/adau17x1.h

index 80c2a06285bbe1f5df619542836bef3a15941c96..12bf24c26818a3ff046a426f56d0cebb356be9a2 100644 (file)
@@ -502,7 +502,7 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
        }
 
        if (adau->sigmadsp) {
-               ret = adau17x1_setup_firmware(adau, params_rate(params));
+               ret = adau17x1_setup_firmware(component, params_rate(params));
                if (ret < 0)
                        return ret;
        }
@@ -835,26 +835,40 @@ bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
 }
 EXPORT_SYMBOL_GPL(adau17x1_volatile_register);
 
-int adau17x1_setup_firmware(struct adau *adau, unsigned int rate)
+int adau17x1_setup_firmware(struct snd_soc_component *component,
+       unsigned int rate)
 {
        int ret;
-       int dspsr;
+       int dspsr, dsp_run;
+       struct adau *adau = snd_soc_component_get_drvdata(component);
+       struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
+
+       snd_soc_dapm_mutex_lock(dapm);
 
        ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr);
        if (ret)
-               return ret;
+               goto err;
+
+       ret = regmap_read(adau->regmap, ADAU17X1_DSP_RUN, &dsp_run);
+       if (ret)
+               goto err;
 
        regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
        regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
+       regmap_write(adau->regmap, ADAU17X1_DSP_RUN, 0);
 
        ret = sigmadsp_setup(adau->sigmadsp, rate);
        if (ret) {
                regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
-               return ret;
+               goto err;
        }
        regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
+       regmap_write(adau->regmap, ADAU17X1_DSP_RUN, dsp_run);
 
-       return 0;
+err:
+       snd_soc_dapm_mutex_unlock(dapm);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(adau17x1_setup_firmware);
 
index a7b1cb770814624f51465664e2dd3e592a91f1df..e6fe87beec07701810be444eee2abd3280c51674 100644 (file)
@@ -68,7 +68,8 @@ int adau17x1_resume(struct snd_soc_component *component);
 
 extern const struct snd_soc_dai_ops adau17x1_dai_ops;
 
-int adau17x1_setup_firmware(struct adau *adau, unsigned int rate);
+int adau17x1_setup_firmware(struct snd_soc_component *component,
+       unsigned int rate);
 bool adau17x1_has_dsp(struct adau *adau);
 
 #define ADAU17X1_CLOCK_CONTROL                 0x4000