diff mbox series

ASoC: wm8960: Remove bitclk relax condition

Message ID 1614683891-29255-1-git-send-email-shengjiu.wang@nxp.com (mailing list archive)
State New, archived
Headers show
Series ASoC: wm8960: Remove bitclk relax condition | expand

Commit Message

Shengjiu Wang March 2, 2021, 11:18 a.m. UTC
From: Daniel Baluta <daniel.baluta@nxp.com>

Using a higher bitclk then expected doesn't always work.
Here is an example:

aplay -Dhw:0,0 -d 5 -r 48000 -f S24_LE -c 2 audio48k24b2c.wav

In this case, the required bitclk is 48000 * 24 * 2 = 2304000
but the closest bitclk that can be derived is 3072000. Since
the clock is faster than expected, it will start to send bytes
from the next channel so the sound will be corrupted.

Fixes: 82bab88910ee ("ASoC: codec: wm8960: Relax bit clock computation when using PLL")
Fixes: 3c01b9ee2ab9 ("ASoC: codec: wm8960: Relax bit clock computation")
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
 sound/soc/codecs/wm8960.c | 29 +++--------------------------
 1 file changed, 3 insertions(+), 26 deletions(-)

Comments

Charles Keepax March 2, 2021, 1:19 p.m. UTC | #1
On Tue, Mar 02, 2021 at 07:18:11PM +0800, Shengjiu Wang wrote:
> From: Daniel Baluta <daniel.baluta@nxp.com>
> 
> Using a higher bitclk then expected doesn't always work.
> Here is an example:
> 
> aplay -Dhw:0,0 -d 5 -r 48000 -f S24_LE -c 2 audio48k24b2c.wav
> 
> In this case, the required bitclk is 48000 * 24 * 2 = 2304000
> but the closest bitclk that can be derived is 3072000. Since
> the clock is faster than expected, it will start to send bytes
> from the next channel so the sound will be corrupted.
> 
> Fixes: 82bab88910ee ("ASoC: codec: wm8960: Relax bit clock computation when using PLL")
> Fixes: 3c01b9ee2ab9 ("ASoC: codec: wm8960: Relax bit clock computation")
> Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
> Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> ---

I think this is probably going to need a much more involved fix.
The problem is that there are systems that depend on this
behaviour, so you can't just flat out revert it. And to be fair
the I2S specification says that bit clock can run at a higher
rate than required for the data, so the behaviour is correct as
well.

Probably the best solution here is to add additional contraints
from the machine driver on which rates/bit depths/channels are
supported.

Thanks,
Charles
diff mbox series

Patch

diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index df351519a3a6..368bec1dfbdb 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -608,10 +608,6 @@  static const int bclk_divs[] = {
  *		- lrclk      = sysclk / dac_divs
  *		- 10 * bclk  = sysclk / bclk_divs
  *
- *	If we cannot find an exact match for (sysclk, lrclk, bclk)
- *	triplet, we relax the bclk such that bclk is chosen as the
- *	closest available frequency greater than expected bclk.
- *
  * @wm8960: codec private data
  * @mclk: MCLK used to derive sysclk
  * @sysclk_idx: sysclk_divs index for found sysclk
@@ -629,7 +625,7 @@  int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
 {
 	int sysclk, bclk, lrclk;
 	int i, j, k;
-	int diff, closest = mclk;
+	int diff;
 
 	/* marker for no match */
 	*bclk_idx = -1;
@@ -653,12 +649,6 @@  int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
 					*bclk_idx = k;
 					break;
 				}
-				if (diff > 0 && closest > diff) {
-					*sysclk_idx = i;
-					*dac_idx = j;
-					*bclk_idx = k;
-					closest = diff;
-				}
 			}
 			if (k != ARRAY_SIZE(bclk_divs))
 				break;
@@ -676,10 +666,6 @@  int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
  *		- freq_out    = sysclk * sysclk_divs
  *		- 10 * sysclk = bclk * bclk_divs
  *
- * 	If we cannot find an exact match for (sysclk, lrclk, bclk)
- * 	triplet, we relax the bclk such that bclk is chosen as the
- * 	closest available frequency greater than expected bclk.
- *
  * @component: component structure
  * @freq_in: input frequency used to derive freq out via PLL
  * @sysclk_idx: sysclk_divs index for found sysclk
@@ -697,14 +683,12 @@  int wm8960_configure_pll(struct snd_soc_component *component, int freq_in,
 {
 	struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);
 	int sysclk, bclk, lrclk, freq_out;
-	int diff, closest, best_freq_out;
+	int diff;
 	int i, j, k;
 
 	bclk = wm8960->bclk;
 	lrclk = wm8960->lrclk;
-	closest = freq_in;
 
-	best_freq_out = -EINVAL;
 	*sysclk_idx = *dac_idx = *bclk_idx = -1;
 
 	for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
@@ -725,18 +709,11 @@  int wm8960_configure_pll(struct snd_soc_component *component, int freq_in,
 					*bclk_idx = k;
 					return freq_out;
 				}
-				if (diff > 0 && closest > diff) {
-					*sysclk_idx = i;
-					*dac_idx = j;
-					*bclk_idx = k;
-					closest = diff;
-					best_freq_out = freq_out;
-				}
 			}
 		}
 	}
 
-	return best_freq_out;
+	return -EINVAL;
 }
 static int wm8960_configure_clocking(struct snd_soc_component *component)
 {