diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index df528e8cb7c9..a14c31eb06d8 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h @@ -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 | \ diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index 8c166a5f338c..98140f449eb3 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c @@ -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, @@ -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, diff --git a/sound/soc/meson/axg-spdifin.c b/sound/soc/meson/axg-spdifin.c index bc2f2849ecfb..e721f579321e 100644 --- a/sound/soc/meson/axg-spdifin.c +++ b/sound/soc/meson/axg-spdifin.c @@ -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); @@ -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; diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 1c3d433cefd2..bf708717635b 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -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, @@ -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; @@ -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, @@ -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) { diff --git a/sound/soc/meson/axg-toddr.c b/sound/soc/meson/axg-toddr.c index 1a0be177b8fe..32ee45cce7f8 100644 --- a/sound/soc/meson/axg-toddr.c +++ b/sound/soc/meson/axg-toddr.c @@ -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, @@ -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,