!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:
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 */
int gpio_nreset;
/* GPIO that disable serial bus, if any */
int gpio_disable;
+ /* enable soft reset workaround */
+ bool enable_soft_reset;
};
/*
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 */
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
gpio_nreset = cs4271plat->gpio_nreset;
amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
+ cs4271->enable_soft_reset = cs4271plat->enable_soft_reset;
}
if (gpio_nreset >= 0)