From: Daniel Mack <daniel@zonque.org>
To: broonie@kernel.org, ryan.lee.analog@gmail.com
Cc: alsa-devel@alsa-project.org, Daniel Mack <daniel@zonque.org>
Subject: [PATCH] ASoC: max98396: Fix TDM mode BSEL settings
Date: Wed, 29 Jun 2022 07:06:30 +0200 [thread overview]
Message-ID: <20220629050630.2848317-1-daniel@zonque.org> (raw)
In TDM mode, the BSEL register value must be set according to table 5 in the
datasheet. This patch adds a lookup function and uses it in
max98396_dai_tdm_slot().
As the first 3 entries can also be used for non-TDM setups, the code re-uses
the same table for such scenarios.
Signed-off-by: Daniel Mack <daniel@zonque.org>
---
sound/soc/codecs/max98396.c | 138 +++++++++++++++++++++++++-----------
sound/soc/codecs/max98396.h | 2 +-
2 files changed, 96 insertions(+), 44 deletions(-)
diff --git a/sound/soc/codecs/max98396.c b/sound/soc/codecs/max98396.c
index f28831f4e74b..1b6f053adba2 100644
--- a/sound/soc/codecs/max98396.c
+++ b/sound/soc/codecs/max98396.c
@@ -438,47 +438,68 @@ static int max98396_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
return 0;
}
-/* BCLKs per LRCLK */
-static const int bclk_sel_table[] = {
- 32, 48, 64, 96, 128, 192, 256, 384, 512, 320,
+#define MAX98396_BSEL_32 0x2
+#define MAX98396_BSEL_48 0x3
+#define MAX98396_BSEL_64 0x4
+#define MAX98396_BSEL_96 0x5
+#define MAX98396_BSEL_128 0x6
+#define MAX98396_BSEL_192 0x7
+#define MAX98396_BSEL_256 0x8
+#define MAX98396_BSEL_384 0x9
+#define MAX98396_BSEL_512 0xa
+#define MAX98396_BSEL_320 0xb
+#define MAX98396_BSEL_250 0xc
+#define MAX98396_BSEL_125 0xd
+
+/* Refer to table 5 in the datasheet */
+static const struct max98396_pcm_config {
+ int in, out, width, bsel, max_sr;
+} max98396_pcm_configs[] = {
+ { .in = 2, .out = 4, .width = 16, .bsel = MAX98396_BSEL_32, .max_sr = 192000 },
+ { .in = 2, .out = 6, .width = 24, .bsel = MAX98396_BSEL_48, .max_sr = 192000 },
+ { .in = 2, .out = 8, .width = 32, .bsel = MAX98396_BSEL_64, .max_sr = 192000 },
+ { .in = 3, .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 192000 },
+ { .in = 4, .out = 8, .width = 16, .bsel = MAX98396_BSEL_64, .max_sr = 192000 },
+ { .in = 4, .out = 12, .width = 24, .bsel = MAX98396_BSEL_96, .max_sr = 192000 },
+ { .in = 4, .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 192000 },
+ { .in = 5, .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 192000 },
+ { .in = 7, .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 192000 },
+ { .in = 2, .out = 4, .width = 16, .bsel = MAX98396_BSEL_32, .max_sr = 96000 },
+ { .in = 2, .out = 6, .width = 24, .bsel = MAX98396_BSEL_48, .max_sr = 96000 },
+ { .in = 2, .out = 8, .width = 32, .bsel = MAX98396_BSEL_64, .max_sr = 96000 },
+ { .in = 3, .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 96000 },
+ { .in = 4, .out = 8, .width = 16, .bsel = MAX98396_BSEL_64, .max_sr = 96000 },
+ { .in = 4, .out = 12, .width = 24, .bsel = MAX98396_BSEL_96, .max_sr = 96000 },
+ { .in = 4, .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 96000 },
+ { .in = 5, .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 96000 },
+ { .in = 7, .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 96000 },
+ { .in = 7, .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 96000 },
+ { .in = 8, .out = 16, .width = 16, .bsel = MAX98396_BSEL_128, .max_sr = 96000 },
+ { .in = 8, .out = 24, .width = 24, .bsel = MAX98396_BSEL_192, .max_sr = 96000 },
+ { .in = 8, .out = 32, .width = 32, .bsel = MAX98396_BSEL_256, .max_sr = 96000 },
+ { .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 96000 },
+ { .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 96000 },
+ { .in = 16, .out = 32, .width = 16, .bsel = MAX98396_BSEL_256, .max_sr = 96000 },
+ { .in = 7, .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 48000 },
+ { .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 48000 },
+ { .in = 10, .out = 40, .width = 32, .bsel = MAX98396_BSEL_320, .max_sr = 48000 },
+ { .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 48000 },
+ { .in = 16, .out = 48, .width = 24, .bsel = MAX98396_BSEL_384, .max_sr = 48000 },
+ { .in = 16, .out = 64, .width = 32, .bsel = MAX98396_BSEL_512, .max_sr = 48000 },
};
-static int max98396_get_bclk_sel(int bclk)
+static int max98396_pcm_config_index(int in_slots, int out_slots, int width)
{
int i;
- /* match BCLKs per LRCLK */
- for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
- if (bclk_sel_table[i] == bclk)
- return i + 2;
- }
- return 0;
-}
-
-static int max98396_set_clock(struct snd_soc_component *component,
- struct snd_pcm_hw_params *params)
-{
- struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component);
- /* BCLK/LRCLK ratio calculation */
- int blr_clk_ratio = params_channels(params) * max98396->ch_size;
- int value;
- if (!max98396->tdm_mode) {
- /* BCLK configuration */
- value = max98396_get_bclk_sel(blr_clk_ratio);
- if (!value) {
- dev_err(component->dev,
- "blr_clk_ratio %d unsupported, format %d\n",
- blr_clk_ratio, params_format(params));
- return -EINVAL;
- }
+ for (i = 0; i < ARRAY_SIZE(max98396_pcm_configs); i++) {
+ const struct max98396_pcm_config *c = &max98396_pcm_configs[i];
- regmap_update_bits(max98396->regmap,
- MAX98396_R2042_PCM_CLK_SETUP,
- MAX98396_PCM_CLK_SETUP_BSEL_MASK,
- value);
+ if (in_slots == c->in && out_slots <= c->out && width == c->width)
+ return i;
}
- return 0;
+ return -1;
}
static int max98396_dai_hw_params(struct snd_pcm_substream *substream,
@@ -489,8 +510,7 @@ static int max98396_dai_hw_params(struct snd_pcm_substream *substream,
struct max98396_priv *max98396 = snd_soc_component_get_drvdata(component);
unsigned int sampling_rate = 0;
unsigned int chan_sz = 0;
- int ret, reg;
- int status;
+ int ret, reg, status, bsel = 0;
bool update = false;
/* pcm mode configuration */
@@ -510,8 +530,6 @@ static int max98396_dai_hw_params(struct snd_pcm_substream *substream,
goto err;
}
- max98396->ch_size = snd_pcm_format_width(params_format(params));
-
dev_dbg(component->dev, "format supported %d",
params_format(params));
@@ -559,6 +577,33 @@ static int max98396_dai_hw_params(struct snd_pcm_substream *substream,
goto err;
}
+ if (max98396->tdm_mode) {
+ if (params_rate(params) > max98396->tdm_max_samplerate) {
+ dev_err(component->dev, "TDM sample rate %d too high",
+ params_rate(params));
+ goto err;
+ }
+ } else {
+ /* BCLK configuration */
+ ret = max98396_pcm_config_index(params_channels(params),
+ params_channels(params),
+ snd_pcm_format_width(params_format(params)));
+ if (ret < 0) {
+ dev_err(component->dev,
+ "no PCM config for %d channels, format %d\n",
+ params_channels(params), params_format(params));
+ goto err;
+ }
+
+ bsel = max98396_pcm_configs[ret].bsel;
+
+ if (params_rate(params) > max98396_pcm_configs[ret].max_sr) {
+ dev_err(component->dev, "sample rate %d too high",
+ params_rate(params));
+ goto err;
+ }
+ }
+
ret = regmap_read(max98396->regmap, MAX98396_R210F_GLOBAL_EN, &status);
if (ret < 0)
goto err;
@@ -604,12 +649,16 @@ static int max98396_dai_hw_params(struct snd_pcm_substream *substream,
MAX98396_IVADC_SR_MASK,
sampling_rate << MAX98396_IVADC_SR_SHIFT);
- ret = max98396_set_clock(component, params);
+ if (bsel)
+ regmap_update_bits(max98396->regmap,
+ MAX98396_R2042_PCM_CLK_SETUP,
+ MAX98396_PCM_CLK_SETUP_BSEL_MASK,
+ bsel);
if (status && update)
max98396_global_enable_onoff(max98396->regmap, true);
- return ret;
+ return 0;
err:
return -EINVAL;
@@ -634,13 +683,16 @@ static int max98396_dai_tdm_slot(struct snd_soc_dai *dai,
max98396->tdm_mode = true;
/* BCLK configuration */
- bsel = max98396_get_bclk_sel(slots * slot_width);
- if (bsel == 0) {
- dev_err(component->dev, "BCLK %d not supported\n",
- slots * slot_width);
+ ret = max98396_pcm_config_index(slots, slots, slot_width);
+ if (ret < 0) {
+ dev_err(component->dev, "no TDM config for %d slots %d bits\n",
+ slots, slot_width);
return -EINVAL;
}
+ bsel = max98396_pcm_configs[ret].bsel;
+ max98396->tdm_max_samplerate = max98396_pcm_configs[ret].max_sr;
+
/* Channel size configuration */
switch (slot_width) {
case 16:
diff --git a/sound/soc/codecs/max98396.h b/sound/soc/codecs/max98396.h
index ff330ef61568..7278c779989a 100644
--- a/sound/soc/codecs/max98396.h
+++ b/sound/soc/codecs/max98396.h
@@ -306,8 +306,8 @@ struct max98396_priv {
unsigned int spkfb_slot;
unsigned int bypass_slot;
bool interleave_mode;
- unsigned int ch_size;
bool tdm_mode;
+ int tdm_max_samplerate;
int device_id;
};
#endif
--
2.36.1
next reply other threads:[~2022-06-29 5:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-29 5:06 Daniel Mack [this message]
2022-06-29 14:05 ` [PATCH] ASoC: max98396: Fix TDM mode BSEL settings Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220629050630.2848317-1-daniel@zonque.org \
--to=daniel@zonque.org \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=ryan.lee.analog@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.