1
0
Fork 0

ASoC: si476x: Fix locking of core

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>
hifive-unleashed-5.1
Mark Brown 2013-10-20 18:14:20 +01:00
parent d6173df35f
commit cfcff69af8
1 changed files with 15 additions and 3 deletions

View 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)