ASoC: si476x: Fix locking of core
authorMark Brown <broonie@linaro.org>
Sun, 20 Oct 2013 17:14:20 +0000 (18:14 +0100)
committerMark Brown <broonie@linaro.org>
Sun, 20 Oct 2013 21:42:02 +0000 (22:42 +0100)
The conversion of the si476x to regmap removed locking of the core during
register updates, allowing things like power state changes for the MFD to
happen during a register update. Avoid this by taking the core lock in the
DAI operations (which are the only things that do register updates) as we
used to do in the open coded register I/O functions.

Signed-off-by: Mark Brown <broonie@linaro.org>
Acked-by: Andrey Smirnov <andrew.smirnov@gmail.com>
sound/soc/codecs/si476x.c

index 03645ce42063ac7ad65462e6b2f386e2d05d5f7a..52e7cb08434bd281354c4a34f520f16c38b0446f 100644 (file)
@@ -73,6 +73,7 @@ static const struct snd_soc_dapm_route si476x_dapm_routes[] = {
 static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
                                    unsigned int fmt)
 {
+       struct si476x_core *core = i2c_mfd_cell_to_core(codec_dai->dev);
        int err;
        u16 format = 0;
 
@@ -136,9 +137,14 @@ static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
+       si476x_core_lock(core);
+
        err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
                                  SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
                                  format);
+
+       si476x_core_unlock(core);
+
        if (err < 0) {
                dev_err(codec_dai->codec->dev, "Failed to set output format\n");
                return err;
@@ -151,6 +157,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *params,
                                  struct snd_soc_dai *dai)
 {
+       struct si476x_core *core = i2c_mfd_cell_to_core(dai->dev);
        int rate, width, err;
 
        rate = params_rate(params);
@@ -176,11 +183,13 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       si476x_core_lock(core);
+
        err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
                            rate);
        if (err < 0) {
                dev_err(dai->codec->dev, "Failed to set sample rate\n");
-               return err;
+               goto out;
        }
 
        err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
@@ -189,10 +198,13 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
                                  (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
        if (err < 0) {
                dev_err(dai->codec->dev, "Failed to set output width\n");
-               return err;
+               goto out;
        }
 
-       return 0;
+out:
+       si476x_core_unlock(core);
+
+       return err;
 }
 
 static int si476x_codec_probe(struct snd_soc_codec *codec)