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:
Родитель
133d2e6188
Коммит
fd23fb9f6b
|
@ -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 @@
|
||||||
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 {
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче