Commit fd23fb9f authored by Daniel Mack's avatar Daniel Mack Committed by Mark Brown

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: default avatarDaniel Mack <zonque@gmail.com>
Acked-by: default avatarAlexander Sverdlin <subaparts@yandex.ru>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 133d2e61
...@@ -20,6 +20,18 @@ Optional properties: ...@@ -20,6 +20,18 @@ Optional properties:
!RESET pin !RESET pin
- cirrus,amuteb-eq-bmutec: When given, the Codec's AMUTEB=BMUTEC flag - cirrus,amuteb-eq-bmutec: When given, the Codec's AMUTEB=BMUTEC flag
is enabled. is enabled.
- cirrus,enable-soft-reset:
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 workaround can be enabled with this DT
property.
Note that this is not needed in case the clocks are stable
throughout the entire runtime of the codec.
Examples: Examples:
......
...@@ -20,6 +20,21 @@ ...@@ -20,6 +20,21 @@
struct cs4271_platform_data { struct cs4271_platform_data {
int gpio_nreset; /* GPIO driving Reset pin, if any */ int gpio_nreset; /* GPIO driving Reset pin, if any */
bool amutec_eq_bmutec; /* flag to enable AMUTEC=BMUTEC */ bool amutec_eq_bmutec; /* flag to enable AMUTEC=BMUTEC */
/*
* 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 workaround can be enabled with the
* following flag.
*
* Note that this is not needed in case the clocks are stable
* throughout the entire runtime of the codec.
*/
bool enable_soft_reset;
}; };
#endif /* __CS4271_H */ #endif /* __CS4271_H */
...@@ -167,6 +167,8 @@ struct cs4271_private { ...@@ -167,6 +167,8 @@ struct cs4271_private {
int gpio_nreset; int gpio_nreset;
/* GPIO that disable serial bus, if any */ /* GPIO that disable serial bus, if any */
int gpio_disable; 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, ...@@ -325,6 +327,33 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream,
int i, ret; int i, ret;
unsigned int ratio, val; 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); cs4271->rate = params_rate(params);
/* Configure DAC */ /* Configure DAC */
...@@ -484,6 +513,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) ...@@ -484,6 +513,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
if (of_get_property(codec->dev->of_node, if (of_get_property(codec->dev->of_node,
"cirrus,amutec-eq-bmutec", NULL)) "cirrus,amutec-eq-bmutec", NULL))
amutec_eq_bmutec = true; amutec_eq_bmutec = true;
if (of_get_property(codec->dev->of_node,
"cirrus,enable-soft-reset", NULL))
cs4271->enable_soft_reset = true;
} }
#endif #endif
...@@ -492,6 +525,7 @@ static int cs4271_probe(struct snd_soc_codec *codec) ...@@ -492,6 +525,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
gpio_nreset = cs4271plat->gpio_nreset; gpio_nreset = cs4271plat->gpio_nreset;
amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
cs4271->enable_soft_reset = cs4271plat->enable_soft_reset;
} }
if (gpio_nreset >= 0) if (gpio_nreset >= 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment