]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: spacemit: move hw constraints from hw_params to startup
authorTroy Mitchell <troy.mitchell@linux.spacemit.com>
Wed, 29 Apr 2026 01:38:47 +0000 (09:38 +0800)
committerMark Brown <broonie@kernel.org>
Wed, 29 Apr 2026 02:41:32 +0000 (11:41 +0900)
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>
sound/soc/spacemit/k1_i2s.c

index 1cb99f1abc7cde3370ca643c8b955132d8a1013a..bb73d32a1b0971d51f2a28c77c9ffc2c316ed811 100644 (file)
@@ -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,