[PATCH] ASoC: fsl_ssi: remove unsupported formats in i2s master mode
Sven Van Asbroeck
thesven73 at gmail.com
Fri Feb 22 02:35:50 AEDT 2019
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 at kernel.org>
Cc: Nicolin Chen <nicoleotsuka at gmail.com>
Cc: Xiubo Li <Xiubo.Lee at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Liam Girdwood <lgirdwood at gmail.com>
Cc: Mark Brown <broonie at kernel.org>
Cc: Jaroslav Kysela <perex at perex.cz>
Cc: Takashi Iwai <tiwai at suse.com>
Signed-off-by: Sven Van Asbroeck <TheSven73 at 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;
}
--
2.17.1
More information about the Linuxppc-dev
mailing list