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>
This commit is contained in:
Daniel Mack
2012-12-10 10:30:04 +01:00
committed by Mark Brown
parent 133d2e6188
commit fd23fb9f6b
3 changed files with 61 additions and 0 deletions

View File

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