diff options
author | Daniel Mack <zonque@gmail.com> | 2012-12-10 10:30:04 +0100 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-12-24 16:53:28 +0100 |
commit | fd23fb9f6bfd43a6e62b2646d18d5ca3edc3ebe3 (patch) | |
tree | a1033cbc88a3ccba164e8d0f6c7469f9efd6713a /sound/soc/codecs/cs4271.c | |
parent | Merge branch 'asoc-fix-cs4271' into asoc-cs4271 (diff) | |
download | linux-fd23fb9f6bfd43a6e62b2646d18d5ca3edc3ebe3.tar.xz linux-fd23fb9f6bfd43a6e62b2646d18d5ca3edc3ebe3.zip |
ALSA: ASoC: cs4271: add optional soft reset workaround
The CS4271 requires its LRCLK and MCLK to be stable before its RESET
line is de-asserted. That also means that clocks cannot be changed
without putting the chip back into hardware reset, which also requires
a complete re-initialization of all registers.
One (undocumented) workaround is to assert and de-assert the PDN bit
in the MODE2 register.
This patch adds a new flag to both the DT bindings as well as to the
platform data to enable that workaround.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Alexander Sverdlin <subaparts@yandex.ru>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/cs4271.c')
-rw-r--r-- | sound/soc/codecs/cs4271.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index ac8742a1f25a..2415a4118dbd 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -167,6 +167,8 @@ struct cs4271_private { int gpio_nreset; /* GPIO that disable serial bus, if any */ int gpio_disable; + /* enable soft reset workaround */ + bool enable_soft_reset; }; /* @@ -325,6 +327,33 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, int i, ret; unsigned int ratio, val; + if (cs4271->enable_soft_reset) { + /* + * Put the codec in soft reset and back again in case it's not + * currently streaming data. This way of bringing the codec in + * sync to the current clocks is not explicitly documented in + * the data sheet, but it seems to work fine, and in contrast + * to a read hardware reset, we don't have to sync back all + * registers every time. + */ + + if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + !dai->capture_active) || + (substream->stream == SNDRV_PCM_STREAM_CAPTURE && + !dai->playback_active)) { + ret = snd_soc_update_bits(codec, CS4271_MODE2, + CS4271_MODE2_PDN, + CS4271_MODE2_PDN); + if (ret < 0) + return ret; + + ret = snd_soc_update_bits(codec, CS4271_MODE2, + CS4271_MODE2_PDN, 0); + if (ret < 0) + return ret; + } + } + cs4271->rate = params_rate(params); /* Configure DAC */ @@ -484,6 +513,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) if (of_get_property(codec->dev->of_node, "cirrus,amutec-eq-bmutec", NULL)) amutec_eq_bmutec = true; + + if (of_get_property(codec->dev->of_node, + "cirrus,enable-soft-reset", NULL)) + cs4271->enable_soft_reset = true; } #endif @@ -492,6 +525,7 @@ static int cs4271_probe(struct snd_soc_codec *codec) gpio_nreset = cs4271plat->gpio_nreset; amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; + cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; } if (gpio_nreset >= 0) |