diff options
author | Daniel Mack <zonque@gmail.com> | 2012-12-10 04:30:04 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-12-24 10:53:28 -0500 |
commit | fd23fb9f6bfd43a6e62b2646d18d5ca3edc3ebe3 (patch) | |
tree | a1033cbc88a3ccba164e8d0f6c7469f9efd6713a | |
parent | 133d2e6188de86df3ed84cd42ac66e9c5d328c04 (diff) |
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>
-rw-r--r-- | Documentation/devicetree/bindings/sound/cs4271.txt | 12 | ||||
-rw-r--r-- | include/sound/cs4271.h | 15 | ||||
-rw-r--r-- | sound/soc/codecs/cs4271.c | 34 |
3 files changed, 61 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/cs4271.txt b/Documentation/devicetree/bindings/sound/cs4271.txt index a850fb9c88ea..e2cd1d7539e5 100644 --- a/Documentation/devicetree/bindings/sound/cs4271.txt +++ b/Documentation/devicetree/bindings/sound/cs4271.txt | |||
@@ -20,6 +20,18 @@ Optional properties: | |||
20 | !RESET pin | 20 | !RESET pin |
21 | - cirrus,amuteb-eq-bmutec: When given, the Codec's AMUTEB=BMUTEC flag | 21 | - cirrus,amuteb-eq-bmutec: When given, the Codec's AMUTEB=BMUTEC flag |
22 | is enabled. | 22 | is enabled. |
23 | - cirrus,enable-soft-reset: | ||
24 | The CS4271 requires its LRCLK and MCLK to be stable before its RESET | ||
25 | line is de-asserted. That also means that clocks cannot be changed | ||
26 | without putting the chip back into hardware reset, which also requires | ||
27 | a complete re-initialization of all registers. | ||
28 | |||
29 | One (undocumented) workaround is to assert and de-assert the PDN bit | ||
30 | in the MODE2 register. This workaround can be enabled with this DT | ||
31 | property. | ||
32 | |||
33 | Note that this is not needed in case the clocks are stable | ||
34 | throughout the entire runtime of the codec. | ||
23 | 35 | ||
24 | Examples: | 36 | Examples: |
25 | 37 | ||
diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h index dd8c48d14ed9..70f45355acaa 100644 --- a/include/sound/cs4271.h +++ b/include/sound/cs4271.h | |||
@@ -20,6 +20,21 @@ | |||
20 | struct cs4271_platform_data { | 20 | struct cs4271_platform_data { |
21 | int gpio_nreset; /* GPIO driving Reset pin, if any */ | 21 | int gpio_nreset; /* GPIO driving Reset pin, if any */ |
22 | bool amutec_eq_bmutec; /* flag to enable AMUTEC=BMUTEC */ | 22 | bool amutec_eq_bmutec; /* flag to enable AMUTEC=BMUTEC */ |
23 | |||
24 | /* | ||
25 | * The CS4271 requires its LRCLK and MCLK to be stable before its RESET | ||
26 | * line is de-asserted. That also means that clocks cannot be changed | ||
27 | * without putting the chip back into hardware reset, which also requires | ||
28 | * a complete re-initialization of all registers. | ||
29 | * | ||
30 | * One (undocumented) workaround is to assert and de-assert the PDN bit | ||
31 | * in the MODE2 register. This workaround can be enabled with the | ||
32 | * following flag. | ||
33 | * | ||
34 | * Note that this is not needed in case the clocks are stable | ||
35 | * throughout the entire runtime of the codec. | ||
36 | */ | ||
37 | bool enable_soft_reset; | ||
23 | }; | 38 | }; |
24 | 39 | ||
25 | #endif /* __CS4271_H */ | 40 | #endif /* __CS4271_H */ |
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 { | |||
167 | int gpio_nreset; | 167 | int gpio_nreset; |
168 | /* GPIO that disable serial bus, if any */ | 168 | /* GPIO that disable serial bus, if any */ |
169 | int gpio_disable; | 169 | int gpio_disable; |
170 | /* enable soft reset workaround */ | ||
171 | bool enable_soft_reset; | ||
170 | }; | 172 | }; |
171 | 173 | ||
172 | /* | 174 | /* |
@@ -325,6 +327,33 @@ static int cs4271_hw_params(struct snd_pcm_substream *substream, | |||
325 | int i, ret; | 327 | int i, ret; |
326 | unsigned int ratio, val; | 328 | unsigned int ratio, val; |
327 | 329 | ||
330 | if (cs4271->enable_soft_reset) { | ||
331 | /* | ||
332 | * Put the codec in soft reset and back again in case it's not | ||
333 | * currently streaming data. This way of bringing the codec in | ||
334 | * sync to the current clocks is not explicitly documented in | ||
335 | * the data sheet, but it seems to work fine, and in contrast | ||
336 | * to a read hardware reset, we don't have to sync back all | ||
337 | * registers every time. | ||
338 | */ | ||
339 | |||
340 | if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
341 | !dai->capture_active) || | ||
342 | (substream->stream == SNDRV_PCM_STREAM_CAPTURE && | ||
343 | !dai->playback_active)) { | ||
344 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | ||
345 | CS4271_MODE2_PDN, | ||
346 | CS4271_MODE2_PDN); | ||
347 | if (ret < 0) | ||
348 | return ret; | ||
349 | |||
350 | ret = snd_soc_update_bits(codec, CS4271_MODE2, | ||
351 | CS4271_MODE2_PDN, 0); | ||
352 | if (ret < 0) | ||
353 | return ret; | ||
354 | } | ||
355 | } | ||
356 | |||
328 | cs4271->rate = params_rate(params); | 357 | cs4271->rate = params_rate(params); |
329 | 358 | ||
330 | /* Configure DAC */ | 359 | /* Configure DAC */ |
@@ -484,6 +513,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
484 | if (of_get_property(codec->dev->of_node, | 513 | if (of_get_property(codec->dev->of_node, |
485 | "cirrus,amutec-eq-bmutec", NULL)) | 514 | "cirrus,amutec-eq-bmutec", NULL)) |
486 | amutec_eq_bmutec = true; | 515 | amutec_eq_bmutec = true; |
516 | |||
517 | if (of_get_property(codec->dev->of_node, | ||
518 | "cirrus,enable-soft-reset", NULL)) | ||
519 | cs4271->enable_soft_reset = true; | ||
487 | } | 520 | } |
488 | #endif | 521 | #endif |
489 | 522 | ||
@@ -492,6 +525,7 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
492 | gpio_nreset = cs4271plat->gpio_nreset; | 525 | gpio_nreset = cs4271plat->gpio_nreset; |
493 | 526 | ||
494 | amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; | 527 | amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; |
528 | cs4271->enable_soft_reset = cs4271plat->enable_soft_reset; | ||
495 | } | 529 | } |
496 | 530 | ||
497 | if (gpio_nreset >= 0) | 531 | if (gpio_nreset >= 0) |