[PATCH 8/8] ASoC: max98396: Fix TDM mode BSEL settings
Daniel Mack
daniel at zonque.org
Fri Jun 24 13:34:56 CEST 2022
On 6/24/22 12:47, Daniel Mack wrote:
> 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 now
> re-uses the same code for such scenarios.
>
> max98396_set_clock() is folded into its only user for clarity.
Sorry, the following hunk is missing from this patch:
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
Will include it in the next round.
Thanks,
Daniel
>
> Signed-off-by: Daniel Mack <daniel at zonque.org>
> ---
> sound/soc/codecs/max98396.c | 124 +++++++++++++++++++++++-------------
> 1 file changed, 81 insertions(+), 43 deletions(-)
>
> diff --git a/sound/soc/codecs/max98396.c b/sound/soc/codecs/max98396.c
> index f28831f4e74b..f1657a5f2140 100644
> --- a/sound/soc/codecs/max98396.c
> +++ b/sound/soc/codecs/max98396.c
> @@ -438,47 +438,55 @@ 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,
> +/* 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 = 0x2, /* 32 */ .max_sr = 192000 },
> + { .in = 2, .out = 6, .width = 24, .bsel = 0x3, /* 48 */ .max_sr = 192000 },
> + { .in = 2, .out = 8, .width = 32, .bsel = 0x4, /* 64 */ .max_sr = 192000 },
> + { .in = 3, .out = 15, .width = 32, .bsel = 0xd, /* 125 */ .max_sr = 192000 },
> + { .in = 4, .out = 8, .width = 16, .bsel = 0x4, /* 64 */ .max_sr = 192000 },
> + { .in = 4, .out = 12, .width = 24, .bsel = 0x5, /* 96 */ .max_sr = 192000 },
> + { .in = 4, .out = 16, .width = 32, .bsel = 0x6, /* 128 */ .max_sr = 192000 },
> + { .in = 5, .out = 15, .width = 24, .bsel = 0xd, /* 125 */ .max_sr = 192000 },
> + { .in = 7, .out = 15, .width = 16, .bsel = 0xd, /* 125 */ .max_sr = 192000 },
> + { .in = 2, .out = 4, .width = 16, .bsel = 0x2, /* 32 */ .max_sr = 96000 },
> + { .in = 2, .out = 6, .width = 24, .bsel = 0x3, /* 48 */ .max_sr = 96000 },
> + { .in = 2, .out = 8, .width = 32, .bsel = 0x4, /* 64 */ .max_sr = 96000 },
> + { .in = 3, .out = 15, .width = 32, .bsel = 0xd, /* 125 */ .max_sr = 96000 },
> + { .in = 4, .out = 8, .width = 16, .bsel = 0x4, /* 64 */ .max_sr = 96000 },
> + { .in = 4, .out = 12, .width = 24, .bsel = 0x5, /* 96 */ .max_sr = 96000 },
> + { .in = 4, .out = 16, .width = 32, .bsel = 0x6, /* 128 */ .max_sr = 96000 },
> + { .in = 5, .out = 15, .width = 24, .bsel = 0xd, /* 125 */ .max_sr = 96000 },
> + { .in = 7, .out = 15, .width = 16, .bsel = 0xd, /* 125 */ .max_sr = 96000 },
> + { .in = 7, .out = 31, .width = 32, .bsel = 0xc, /* 250 */ .max_sr = 96000 },
> + { .in = 8, .out = 16, .width = 16, .bsel = 0x6, /* 128 */ .max_sr = 96000 },
> + { .in = 8, .out = 24, .width = 24, .bsel = 0x7, /* 192 */ .max_sr = 96000 },
> + { .in = 8, .out = 32, .width = 32, .bsel = 0x8, /* 256 */ .max_sr = 96000 },
> + { .in = 10, .out = 31, .width = 24, .bsel = 0xc, /* 250 */ .max_sr = 96000 },
> + { .in = 15, .out = 31, .width = 16, .bsel = 0xc, /* 250 */ .max_sr = 96000 },
> + { .in = 16, .out = 32, .width = 16, .bsel = 0x8, /* 256 */ .max_sr = 96000 },
> + { .in = 7, .out = 31, .width = 32, .bsel = 0xc, /* 250 */ .max_sr = 48000 },
> + { .in = 10, .out = 31, .width = 24, .bsel = 0xc, /* 250 */ .max_sr = 48000 },
> + { .in = 10, .out = 40, .width = 32, .bsel = 0xb, /* 320 */ .max_sr = 48000 },
> + { .in = 15, .out = 31, .width = 16, .bsel = 0xc, /* 250 */ .max_sr = 48000 },
> + { .in = 16, .out = 48, .width = 24, .bsel = 0x9, /* 384 */ .max_sr = 48000 },
> + { .in = 16, .out = 64, .width = 32, .bsel = 0xa, /* 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 +497,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;
> bool update = false;
>
> /* pcm mode configuration */
> @@ -510,8 +517,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 +564,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 +636,15 @@ 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);
> + 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 +669,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:
More information about the Alsa-devel
mailing list