Mark Brown broonie@kernel.org writes:
Given that the datasheet quotes a maximum MCLK of 51.2MHz I suspect that this is far too high and that performance is degrading well before this point, it sounds like it just so happens that you noticed issues on a machine with this MCLK rather than that's based on the spec. I would instead suggest applying the MCLK divider in any case where we can do so and still generate suitable clocking for the rest of the system, or at least hit 256fs (the datasheet quotes 256/384fs on the front page which suggests it's targetting 256fs, that'd be a fairly normal number, and there's mention of 12/24MHz USB clocks being directly usable). Doing this should either make no odds or result in better performance.
Not 100% sure what checks should be done for a MCLK to determine if it generates suitable clocking. Would something along this patch make sense?
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index a8f347f1affb..667648de8105 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -470,19 +470,36 @@ 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; + + do { + /* Validate supported sample rates that are autodetected from MCLK */ + for (i = 0; i < NR_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 == NR_SUPPORTED_MCLK_LRCK_RATIOS) { + if (clk == es8316->sysclk) + return -EINVAL; + else + clk = es8316->sysclk; + } else { + clk_valid = true; + } + } while(!clk_valid);
- /* Validate supported sample rates that are autodetected from MCLK */ - for (i = 0; i < NR_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 == NR_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: