Skip to content

Commit

Permalink
ALSA: ASoC: cs4271: add optional soft reset workaround
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
zonque authored and broonie committed Dec 24, 2012
1 parent 133d2e6 commit fd23fb9
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Documentation/devicetree/bindings/sound/cs4271.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ Optional properties:
!RESET pin
- cirrus,amuteb-eq-bmutec: When given, the Codec's AMUTEB=BMUTEC flag
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:

Expand Down
15 changes: 15 additions & 0 deletions include/sound/cs4271.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@
struct cs4271_platform_data {
int gpio_nreset; /* GPIO driving Reset pin, if any */
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 */
34 changes: 34 additions & 0 deletions sound/soc/codecs/cs4271.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/*
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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

Expand All @@ -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)
Expand Down

0 comments on commit fd23fb9

Please sign in to comment.