summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorTroy Mitchell <troy.mitchell@linux.spacemit.com>2026-04-29 09:38:47 +0800
committerMark Brown <broonie@kernel.org>2026-04-29 11:41:32 +0900
commit6b4afbaaa342eaa52172e0be5ef8d1fcbf9ff460 (patch)
tree9fa5eb2c0361d0dcf882fb1b8f76c95c0ad076c4 /sound
parenta201aef1a88b675e9eb8487e27d14e2eef3cef80 (diff)
ASoC: spacemit: move hw constraints from hw_params to startup
Hardware constraints should be applied in the startup callback rather than hw_params, as hw_params may be called too late for the constraints to take effect properly. Move the channel count and format constraints for I2S and DSP_A/DSP_B modes into a new startup callback. This also tightens the I2S mode channel constraint from 1-2 to exactly 2, matching the actual hardware behavior. Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com> Link: https://patch.msgid.link/20260429-k3-i2s-v1-2-2fe99db11ecb@linux.spacemit.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/spacemit/k1_i2s.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c
index 1cb99f1abc7c..bb73d32a1b09 100644
--- a/sound/soc/spacemit/k1_i2s.c
+++ b/sound/soc/spacemit/k1_i2s.c
@@ -106,6 +106,37 @@ static void spacemit_i2s_init(struct spacemit_i2s_dev *i2s)
writel(0, i2s->base + SSINTEN);
}
+static int spacemit_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
+
+ switch (i2s->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ 2, 2);
+ snd_pcm_hw_constraint_mask64(substream->runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_FMTBIT_S16_LE);
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ 1, 1);
+ snd_pcm_hw_constraint_mask64(substream->runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_FMTBIT_S32_LE);
+ break;
+ default:
+ dev_dbg(i2s->dev, "unexpected format type");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -157,22 +188,9 @@ static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
dma_data->maxburst = 32;
dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
}
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- 1, 2);
- snd_pcm_hw_constraint_mask64(substream->runtime,
- SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_FMTBIT_S16_LE);
break;
case SND_SOC_DAIFMT_DSP_A:
case SND_SOC_DAIFMT_DSP_B:
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_CHANNELS,
- 1, 1);
- snd_pcm_hw_constraint_mask64(substream->runtime,
- SNDRV_PCM_HW_PARAM_FORMAT,
- SNDRV_PCM_FMTBIT_S32_LE);
break;
default:
dev_dbg(i2s->dev, "unexpected format type");
@@ -303,6 +321,7 @@ static int spacemit_i2s_dai_remove(struct snd_soc_dai *dai)
static const struct snd_soc_dai_ops spacemit_i2s_dai_ops = {
.probe = spacemit_i2s_dai_probe,
.remove = spacemit_i2s_dai_remove,
+ .startup = spacemit_i2s_startup,
.hw_params = spacemit_i2s_hw_params,
.set_sysclk = spacemit_i2s_set_sysclk,
.set_fmt = spacemit_i2s_set_fmt,