summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/es8316.c45
-rw-r--r--sound/soc/codecs/es8316.h3
2 files changed, 37 insertions, 11 deletions
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index a1c3e10c3cf1..e53b2856d625 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -469,19 +469,42 @@ static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
u8 bclk_divider;
u16 lrck_divider;
int i;
+ unsigned int clk = es8316->sysclk / 2;
+ bool clk_valid = false;
+
+ /* We will start with halved sysclk and see if we can use it
+ * for proper clocking. This is to minimise the risk of running
+ * the CODEC with a too high frequency. We have an SKU where
+ * the sysclk frequency is 48Mhz and this causes the sound to be
+ * sped up. If we can run with a halved sysclk, we will use it,
+ * if we can't use it, then full sysclk will be used.
+ */
+ do {
+ /* Validate supported sample rates that are autodetected from MCLK */
+ for (i = 0; i < ARRAY_SIZE(supported_mclk_lrck_ratios); i++) {
+ const unsigned int ratio = supported_mclk_lrck_ratios[i];
+
+ if (clk % ratio != 0)
+ continue;
+ if (clk / ratio == params_rate(params))
+ break;
+ }
+ if (i == ARRAY_SIZE(supported_mclk_lrck_ratios)) {
+ if (clk == es8316->sysclk)
+ return -EINVAL;
+ clk = es8316->sysclk;
+ } else {
+ clk_valid = true;
+ }
+ } while (!clk_valid);
- /* Validate supported sample rates that are autodetected from MCLK */
- for (i = 0; i < ARRAY_SIZE(supported_mclk_lrck_ratios); i++) {
- const unsigned int ratio = supported_mclk_lrck_ratios[i];
-
- if (es8316->sysclk % ratio != 0)
- continue;
- if (es8316->sysclk / ratio == params_rate(params))
- break;
+ if (clk != es8316->sysclk) {
+ snd_soc_component_update_bits(component, ES8316_CLKMGR_CLKSW,
+ ES8316_CLKMGR_CLKSW_MCLK_DIV,
+ ES8316_CLKMGR_CLKSW_MCLK_DIV);
}
- if (i == ARRAY_SIZE(supported_mclk_lrck_ratios))
- return -EINVAL;
- lrck_divider = es8316->sysclk / params_rate(params);
+
+ lrck_divider = clk / params_rate(params);
bclk_divider = lrck_divider / 4;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
diff --git a/sound/soc/codecs/es8316.h b/sound/soc/codecs/es8316.h
index c335138e2837..0ff16f948690 100644
--- a/sound/soc/codecs/es8316.h
+++ b/sound/soc/codecs/es8316.h
@@ -129,4 +129,7 @@
#define ES8316_GPIO_FLAG_GM_NOT_SHORTED 0x02
#define ES8316_GPIO_FLAG_HP_NOT_INSERTED 0x04
+/* ES8316_CLKMGR_CLKSW */
+#define ES8316_CLKMGR_CLKSW_MCLK_DIV 0x80
+
#endif