summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2024-02-26 18:30:38 +0000
committerMark Brown <broonie@kernel.org>2024-02-26 18:30:38 +0000
commitb86143776573c2276a6e5b5ec99e92b12297a9d5 (patch)
tree90db67a1cc9e7139e9e9d81d2a29efed90f721b3 /sound
parent306904db10e1d839b568809d5c505618062e2d63 (diff)
parent8b410b3c46128f1eee78f1182731b84d9d2e79ef (diff)
downloadlinux-stable-b86143776573c2276a6e5b5ec99e92b12297a9d5.tar.gz
linux-stable-b86143776573c2276a6e5b5ec99e92b12297a9d5.tar.bz2
linux-stable-b86143776573c2276a6e5b5ec99e92b12297a9d5.zip
ASoC: meson: axg fixes and clean-up
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.
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/meson/axg-fifo.h2
-rw-r--r--sound/soc/meson/axg-frddr.c8
-rw-r--r--sound/soc/meson/axg-spdifin.c6
-rw-r--r--sound/soc/meson/axg-tdm-interface.c31
-rw-r--r--sound/soc/meson/axg-toddr.c8
5 files changed, 36 insertions, 19 deletions
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,