Skip to content

Commit

Permalink
ASoC: meson: axg fixes and clean-up
Browse files Browse the repository at this point in the history
Merge series from Jerome Brunet <jbrunet@baylibre.com>:

This are various fixes and clean up gathered while working on Amlogic audio
support. These help better handle higher and unusual clock configuration
for TDM, SPDIF or PDM.
  • Loading branch information
Mark Brown committed Feb 26, 2024
2 parents 306904d + 8b410b3 commit b861437
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 19 deletions.
2 changes: 0 additions & 2 deletions sound/soc/meson/axg-fifo.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ struct snd_soc_dai_driver;
struct snd_soc_pcm_runtime;

#define AXG_FIFO_CH_MAX 128
#define AXG_FIFO_RATES (SNDRV_PCM_RATE_5512 | \
SNDRV_PCM_RATE_8000_384000)
#define AXG_FIFO_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S20_LE | \
Expand Down
8 changes: 6 additions & 2 deletions sound/soc/meson/axg-frddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ static struct snd_soc_dai_driver axg_frddr_dai_drv = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = AXG_FIFO_CH_MAX,
.rates = AXG_FIFO_RATES,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 5515,
.rate_max = 384000,
.formats = AXG_FIFO_FORMATS,
},
.ops = &axg_frddr_ops,
Expand Down Expand Up @@ -184,7 +186,9 @@ static struct snd_soc_dai_driver g12a_frddr_dai_drv = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = AXG_FIFO_CH_MAX,
.rates = AXG_FIFO_RATES,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 5515,
.rate_max = 384000,
.formats = AXG_FIFO_FORMATS,
},
.ops = &g12a_frddr_ops,
Expand Down
6 changes: 3 additions & 3 deletions sound/soc/meson/axg-spdifin.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ static int axg_spdifin_sample_mode_config(struct snd_soc_dai *dai,
SPDIFIN_CTRL1_BASE_TIMER,
FIELD_PREP(SPDIFIN_CTRL1_BASE_TIMER, rate / 1000));

/* Threshold based on the minimum width between two edges */
/* Threshold based on the maximum width between two edges */
regmap_update_bits(priv->map, SPDIFIN_CTRL0,
SPDIFIN_CTRL0_WIDTH_SEL, SPDIFIN_CTRL0_WIDTH_SEL);
SPDIFIN_CTRL0_WIDTH_SEL, 0);

/* Calculate the last timer which has no threshold */
t_next = axg_spdifin_mode_timer(priv, i, rate);
Expand All @@ -199,7 +199,7 @@ static int axg_spdifin_sample_mode_config(struct snd_soc_dai *dai,
axg_spdifin_write_timer(priv->map, i, t);

/* Set the threshold value */
axg_spdifin_write_threshold(priv->map, i, t + t_next);
axg_spdifin_write_threshold(priv->map, i, 3 * (t + t_next));

/* Save the current timer for the next threshold calculation */
t_next = t;
Expand Down
31 changes: 21 additions & 10 deletions sound/soc/meson/axg-tdm-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

#include "axg-tdm.h"

/* Maximum bit clock frequency according the datasheets */
#define MAX_SCLK 100000000 /* Hz */

enum {
TDM_IFACE_PAD,
TDM_IFACE_LOOPBACK,
Expand Down Expand Up @@ -130,7 +133,7 @@ static int axg_tdm_iface_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)

case SND_SOC_DAIFMT_BP_FC:
case SND_SOC_DAIFMT_BC_FP:
dev_err(dai->dev, "only CBS_CFS and CBM_CFM are supported\n");
dev_err(dai->dev, "only BP_FP and BC_FC are supported\n");
fallthrough;
default:
return -EINVAL;
Expand All @@ -153,19 +156,27 @@ static int axg_tdm_iface_startup(struct snd_pcm_substream *substream,
return -EINVAL;
}

/* Apply component wide rate symmetry */
if (snd_soc_component_active(dai->component)) {
/* Apply component wide rate symmetry */
ret = snd_pcm_hw_constraint_single(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
iface->rate);
if (ret < 0) {
dev_err(dai->dev,
"can't set iface rate constraint\n");
return ret;
}

} else {
/* Limit rate according to the slot number and width */
unsigned int max_rate =
MAX_SCLK / (iface->slots * iface->slot_width);
ret = snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
0, max_rate);
}

return 0;
if (ret < 0)
dev_err(dai->dev, "can't set iface rate constraint\n");
else
ret = 0;

return ret;
}

static int axg_tdm_iface_set_stream(struct snd_pcm_substream *substream,
Expand Down Expand Up @@ -264,8 +275,8 @@ static int axg_tdm_iface_set_sclk(struct snd_soc_dai *dai,
srate = iface->slots * iface->slot_width * params_rate(params);

if (!iface->mclk_rate) {
/* If no specific mclk is requested, default to bit clock * 4 */
clk_set_rate(iface->mclk, 4 * srate);
/* If no specific mclk is requested, default to bit clock * 2 */
clk_set_rate(iface->mclk, 2 * srate);
} else {
/* Check if we can actually get the bit clock from mclk */
if (iface->mclk_rate % srate) {
Expand Down
8 changes: 6 additions & 2 deletions sound/soc/meson/axg-toddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ static struct snd_soc_dai_driver axg_toddr_dai_drv = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = AXG_FIFO_CH_MAX,
.rates = AXG_FIFO_RATES,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 5515,
.rate_max = 384000,
.formats = AXG_FIFO_FORMATS,
},
.ops = &axg_toddr_ops,
Expand Down Expand Up @@ -226,7 +228,9 @@ static struct snd_soc_dai_driver g12a_toddr_dai_drv = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = AXG_FIFO_CH_MAX,
.rates = AXG_FIFO_RATES,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 5515,
.rate_max = 384000,
.formats = AXG_FIFO_FORMATS,
},
.ops = &g12a_toddr_ops,
Expand Down

0 comments on commit b861437

Please sign in to comment.