[alsa-devel] [PATCH] ASoC: fsl_ssi: remove unsupported formats in i2s master mode
Quote from the ssi manual: "The word length is fixed to 32 in I2S Master mode and the WL bits determine the number of bits that will contain valid data (out of the 32 transmitted/received bits in each channel)." (61.8.1.4, page 5138, IMX6DQRM Rev. 3, 07/2015)
In other words, in i2s master mode, we always get 32 physical bits/channel, no matter what.
However, the supported list of formats for this ssi contains S8, S16_XX, S18_3XX, and S20_3XX, which have 8, 16, 24 and 24 physical bits/channel respectively. If one of these is selected in i2s master mode, the format generated by the ssi will be incorrect.
Fix by constraining the frame bits in i2s master mode to 32 * channels. This will filter out those formats that the ssi cannot support.
Tested on imx6 with tda998x and sgtl5k codecs.
Cc: Timur Tabi timur@kernel.org Cc: Nicolin Chen nicoleotsuka@gmail.com Cc: Xiubo Li Xiubo.Lee@gmail.com Cc: Fabio Estevam festevam@gmail.com Cc: Liam Girdwood lgirdwood@gmail.com Cc: Mark Brown broonie@kernel.org Cc: Jaroslav Kysela perex@perex.cz Cc: Takashi Iwai tiwai@suse.com Signed-off-by: Sven Van Asbroeck TheSven73@gmail.com --- sound/soc/fsl/fsl_ssi.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 0a648229e643..3d375f60ecf4 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -627,6 +627,28 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi) regmap_write(regs, REG_SSI_SOR, SSI_SOR_WAIT(3)); }
+static int fsl_ssi_hw_rule_i2s_master(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *it = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_FRAME_BITS); + struct fsl_ssi *ssi = rule->private; + struct snd_interval t; + + if (!fsl_ssi_is_i2s_master(ssi)) + return 0; + + /* + * In i2s master mode, the ssi always generates 32 physical + * bits/channel. Filter out formats that don't have 32 physical + * bits/channel, they are unsupported. + */ + memset(&t, 0, sizeof(t)); + t.min = t.max = params_channels(params) * 32; + + return snd_interval_refine(it, &t); +} + static int fsl_ssi_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -648,6 +670,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
+ snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FRAME_BITS, + fsl_ssi_hw_rule_i2s_master, ssi, + SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS, + -1); + return 0; }
On Thu, Feb 21, 2019 at 10:35 AM Sven Van Asbroeck thesven73@gmail.com wrote:
Fix by constraining the frame bits in i2s master mode to 32 * channels. This will filter out those formats that the ssi cannot support.
Russell King (ARM Linux) informs me that this is not correct, and that the problem should be approached differently.
Please remove from consideration if you hadn't done so already. Thanks :)
participants (1)
-
Sven Van Asbroeck