diff mbox series

[1/4] ASoC: es8316: Enable support for S32 LE format and MCLK div by 2

Message ID 20230320203519.20137-2-posteuca@mutex.one (mailing list archive)
State New, archived
Headers show
Series ASoC: amd: acp: Add sound support for a line of HUAWEI laptops | expand

Commit Message

Marian Postevca March 20, 2023, 8:35 p.m. UTC
To properly support a line of Huawei laptops with AMD CPU and a
ES8336 codec connected to the ACP3X module we need to enable
the S32 LE format and the codec option to divide the MCLK by 2.

The option to divide the MCLK will be enabled for one SKU with a
48Mhz MCLK. This frequency seems to be too high for the codec and
leads to distorted sounds when the option is not enabled.

Signed-off-by: Marian Postevca <posteuca@mutex.one>
---
 sound/soc/codecs/es8316.c | 21 +++++++++++++++++----
 sound/soc/codecs/es8316.h |  3 +++
 2 files changed, 20 insertions(+), 4 deletions(-)

Comments

Mark Brown March 20, 2023, 8:43 p.m. UTC | #1
On Mon, Mar 20, 2023 at 10:35:16PM +0200, Marian Postevca wrote:

> To properly support a line of Huawei laptops with AMD CPU and a
> ES8336 codec connected to the ACP3X module we need to enable
> the S32 LE format and the codec option to divide the MCLK by 2.

The 32 bit support and MCLK division are two separate changes so should
be two separate patches.

> -	lrck_divider = es8316->sysclk / params_rate(params);
> +
> +	mclk_div_option = device_property_read_bool(component->dev,
> +						    "everest,mclk-div-by-2");
> +	if (mclk_div_option) {

This introduces a DT property but there's no documentation for it, but I
don't see why we'd want this in the bindings - the driver should be able
to tell from the input clock rate and required output/internal clocks if
it needs to divide MCLK.
Marian Postevca March 21, 2023, 5:09 p.m. UTC | #2
Thanks for taking the time to review this series of patches.

Mark Brown <broonie@kernel.org> writes:

> On Mon, Mar 20, 2023 at 10:35:16PM +0200, Marian Postevca wrote:
>
>> To properly support a line of Huawei laptops with AMD CPU and a
>> ES8336 codec connected to the ACP3X module we need to enable
>> the S32 LE format and the codec option to divide the MCLK by 2.
>
> The 32 bit support and MCLK division are two separate changes so should
> be two separate patches.
>

Ok, no problem, I just thought that a separate commit for one line was overkill.

>> -	lrck_divider = es8316->sysclk / params_rate(params);
>> +
>> +	mclk_div_option = device_property_read_bool(component->dev,
>> +						    "everest,mclk-div-by-2");
>> +	if (mclk_div_option) {
>
> This introduces a DT property but there's no documentation for it, but I
> don't see why we'd want this in the bindings - the driver should be able
> to tell from the input clock rate and required output/internal clocks if
> it needs to divide MCLK.

The problem here is that I have no knowledge what is the maximum MCLK
that the codec accepts. According to the datasheet the maximum supported
frequency of MCLK is 51.2 Mhz. But this doesn't seem to be the case in
practice since a MCLK of 48Mhz causes noises in the sound output.
The idea to divide the MCLK by 2 was proposed by a Everest Semiconductor
engineer.
So I don't know how to make this generic enough to be activated from the
codec driver.

I cced the Everest Semiconductor engineers, maybe they have a proposal
on how to activate this.
Mark Brown March 21, 2023, 5:21 p.m. UTC | #3
On Tue, Mar 21, 2023 at 07:09:43PM +0200, Marian Postevca wrote:
> Mark Brown <broonie@kernel.org> writes:
> > On Mon, Mar 20, 2023 at 10:35:16PM +0200, Marian Postevca wrote:

> > This introduces a DT property but there's no documentation for it, but I
> > don't see why we'd want this in the bindings - the driver should be able
> > to tell from the input clock rate and required output/internal clocks if
> > it needs to divide MCLK.

> The problem here is that I have no knowledge what is the maximum MCLK
> that the codec accepts. According to the datasheet the maximum supported
> frequency of MCLK is 51.2 Mhz. But this doesn't seem to be the case in
> practice since a MCLK of 48Mhz causes noises in the sound output.
> The idea to divide the MCLK by 2 was proposed by a Everest Semiconductor
> engineer.
> So I don't know how to make this generic enough to be activated from the
> codec driver.

The usual constraint would be that MCLK can be at most some multiple of
LRCLK or something similar (are all the other dividers in the chip set
sensibly for the full scale MCLK?).  In any case you're clearly aware of
a specific case where it needs to be divided down which can be
identified even if you're concerned about dividing down for other cases.
diff mbox series

Patch

diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 056c3082fe02..acf21ef59b34 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -26,10 +26,11 @@ 
 /* In slave mode at single speed, the codec is documented as accepting 5
  * MCLK/LRCK ratios, but we also add ratio 400, which is commonly used on
  * Intel Cherry Trail platforms (19.2MHz MCLK, 48kHz LRCK).
+ * Ratio 1000 is needed for at least one SKU where MCLK is 48Mhz.
  */
-#define NR_SUPPORTED_MCLK_LRCK_RATIOS 6
+#define NR_SUPPORTED_MCLK_LRCK_RATIOS 7
 static const unsigned int supported_mclk_lrck_ratios[] = {
-	256, 384, 400, 512, 768, 1024
+	256, 384, 400, 512, 768, 1000, 1024
 };
 
 struct es8316_priv {
@@ -465,6 +466,8 @@  static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
 	u8 bclk_divider;
 	u16 lrck_divider;
 	int i;
+	bool mclk_div_option = false;
+	unsigned int mclk_div = 1;
 
 	/* Validate supported sample rates that are autodetected from MCLK */
 	for (i = 0; i < NR_SUPPORTED_MCLK_LRCK_RATIOS; i++) {
@@ -477,7 +480,17 @@  static int es8316_pcm_hw_params(struct snd_pcm_substream *substream,
 	}
 	if (i == NR_SUPPORTED_MCLK_LRCK_RATIOS)
 		return -EINVAL;
-	lrck_divider = es8316->sysclk / params_rate(params);
+
+	mclk_div_option = device_property_read_bool(component->dev,
+						    "everest,mclk-div-by-2");
+	if (mclk_div_option) {
+		snd_soc_component_update_bits(component, ES8316_CLKMGR_CLKSW,
+					      ES8316_CLKMGR_CLKSW_MCLK_DIV,
+					      ES8316_CLKMGR_CLKSW_MCLK_DIV);
+		mclk_div = 2;
+	}
+
+	lrck_divider = es8316->sysclk / params_rate(params) / mclk_div;
 	bclk_divider = lrck_divider / 4;
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
@@ -520,7 +533,7 @@  static int es8316_mute(struct snd_soc_dai *dai, int mute, int direction)
 }
 
 #define ES8316_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
-			SNDRV_PCM_FMTBIT_S24_LE)
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dai_ops es8316_ops = {
 	.startup = es8316_pcm_startup,
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