The I2S cores used in the H3 onwards support 32-bit sample rates.
Support these by adding a per-variant PCM format list.
Signed-off-by: John Watts <[email protected]>
---
This patch enables support for 32-bit audio in the sunxi I2S driver.
I have only tested this on the Allwinner T113 but I'm fairly
certain it will work on older boards.
---
Changes in v2:
- Specify PCM formats for each variant instead of failing in hw_params
- Link to v1: https://lore.kernel.org/r/[email protected]
---
sound/soc/sunxi/sun4i-i2s.c | 33 ++++++++++++++++++++++++++++-----
1 file changed, 28 insertions(+), 5 deletions(-)
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index a736f632bf0b..59830f2a0d30 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -156,6 +156,7 @@ struct sun4i_i2s;
/**
* struct sun4i_i2s_quirks - Differences between SoC variants.
* @has_reset: SoC needs reset deasserted.
+ * @pcm_formats: available PCM formats
* @reg_offset_txdata: offset of the tx fifo.
* @sun4i_i2s_regmap: regmap config to use.
* @field_clkdiv_mclk_en: regmap field to enable mclk output.
@@ -175,6 +176,7 @@ struct sun4i_i2s;
*/
struct sun4i_i2s_quirks {
bool has_reset;
+ snd_pcm_format_t pcm_formats;
unsigned int reg_offset_txdata; /* TX FIFO */
const struct regmap_config *sun4i_i2s_regmap;
@@ -1092,8 +1094,18 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
return 0;
}
+static int sun4i_i2s_dai_startup(struct snd_pcm_substream *sub, struct snd_soc_dai *dai)
+{
+ struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+ struct snd_pcm_runtime *runtime = sub->runtime;
+
+ return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
+ i2s->variant->pcm_formats);
+}
+
static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = {
.probe = sun4i_i2s_dai_probe,
+ .startup = sun4i_i2s_dai_startup,
.hw_params = sun4i_i2s_hw_params,
.set_fmt = sun4i_i2s_set_fmt,
.set_sysclk = sun4i_i2s_set_sysclk,
@@ -1101,9 +1113,10 @@ static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = {
.trigger = sun4i_i2s_trigger,
};
-#define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S20_LE | \
- SNDRV_PCM_FMTBIT_S24_LE)
+#define SUN4I_FORMATS_ALL (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver sun4i_i2s_dai = {
.capture = {
@@ -1111,14 +1124,14 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = {
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_8000_192000,
- .formats = SUN4I_FORMATS,
+ .formats = SUN4I_FORMATS_ALL,
},
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_8000_192000,
- .formats = SUN4I_FORMATS,
+ .formats = SUN4I_FORMATS_ALL,
},
.ops = &sun4i_i2s_dai_ops,
.symmetric_rate = 1,
@@ -1340,8 +1353,12 @@ static int sun4i_i2s_runtime_suspend(struct device *dev)
return 0;
}
+#define SUN4I_FORMATS_A10 (SUN4I_FORMATS_ALL & ~SNDRV_PCM_FMTBIT_S32_LE)
+#define SUN4I_FORMATS_H3 SUN4I_FORMATS_ALL
+
static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
.has_reset = false,
+ .pcm_formats = SUN4I_FORMATS_A10,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
@@ -1360,6 +1377,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
.has_reset = true,
+ .pcm_formats = SUN4I_FORMATS_A10,
.reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
@@ -1383,6 +1401,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
*/
static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
.has_reset = true,
+ .pcm_formats = SUN4I_FORMATS_A10,
.reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
@@ -1401,6 +1420,7 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
.has_reset = true,
+ .pcm_formats = SUN4I_FORMATS_H3,
.reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun8i_i2s_regmap_config,
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
@@ -1419,6 +1439,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
.has_reset = true,
+ .pcm_formats = SUN4I_FORMATS_H3,
.reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
@@ -1437,6 +1458,7 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = {
.has_reset = true,
+ .pcm_formats = SUN4I_FORMATS_H3,
.reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config,
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
@@ -1455,6 +1477,7 @@ static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = {
static const struct sun4i_i2s_quirks sun50i_r329_i2s_quirks = {
.has_reset = true,
+ .pcm_formats = SUN4I_FORMATS_H3,
.reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
.sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config,
.field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
---
base-commit: 13227c2baa6b345451128828c9c2b0ec3868bd0d
change-id: 20240326-sunxi_s32-f2ab25b8e688
Best regards,
--
John Watts <[email protected]>
Dne sreda, 3. april 2024 ob 05:47:35 CEST je John Watts napisal(a):
> The I2S cores used in the H3 onwards support 32-bit sample rates.
> Support these by adding a per-variant PCM format list.
>
> Signed-off-by: John Watts <[email protected]>
Acked-by: Jernej Skrabec <[email protected]>
Best regards,
Jernej
> ---
> This patch enables support for 32-bit audio in the sunxi I2S driver.
>
> I have only tested this on the Allwinner T113 but I'm fairly
> certain it will work on older boards.
> ---
> Changes in v2:
> - Specify PCM formats for each variant instead of failing in hw_params
> - Link to v1: https://lore.kernel.org/r/[email protected]
> ---
> sound/soc/sunxi/sun4i-i2s.c | 33 ++++++++++++++++++++++++++++-----
> 1 file changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
> index a736f632bf0b..59830f2a0d30 100644
> --- a/sound/soc/sunxi/sun4i-i2s.c
> +++ b/sound/soc/sunxi/sun4i-i2s.c
> @@ -156,6 +156,7 @@ struct sun4i_i2s;
> /**
> * struct sun4i_i2s_quirks - Differences between SoC variants.
> * @has_reset: SoC needs reset deasserted.
> + * @pcm_formats: available PCM formats
> * @reg_offset_txdata: offset of the tx fifo.
> * @sun4i_i2s_regmap: regmap config to use.
> * @field_clkdiv_mclk_en: regmap field to enable mclk output.
> @@ -175,6 +176,7 @@ struct sun4i_i2s;
> */
> struct sun4i_i2s_quirks {
> bool has_reset;
> + snd_pcm_format_t pcm_formats;
> unsigned int reg_offset_txdata; /* TX FIFO */
> const struct regmap_config *sun4i_i2s_regmap;
>
> @@ -1092,8 +1094,18 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
> return 0;
> }
>
> +static int sun4i_i2s_dai_startup(struct snd_pcm_substream *sub, struct snd_soc_dai *dai)
> +{
> + struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
> + struct snd_pcm_runtime *runtime = sub->runtime;
> +
> + return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT,
> + i2s->variant->pcm_formats);
> +}
> +
> static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = {
> .probe = sun4i_i2s_dai_probe,
> + .startup = sun4i_i2s_dai_startup,
> .hw_params = sun4i_i2s_hw_params,
> .set_fmt = sun4i_i2s_set_fmt,
> .set_sysclk = sun4i_i2s_set_sysclk,
> @@ -1101,9 +1113,10 @@ static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = {
> .trigger = sun4i_i2s_trigger,
> };
>
> -#define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
> - SNDRV_PCM_FMTBIT_S20_LE | \
> - SNDRV_PCM_FMTBIT_S24_LE)
> +#define SUN4I_FORMATS_ALL (SNDRV_PCM_FMTBIT_S16_LE | \
> + SNDRV_PCM_FMTBIT_S20_LE | \
> + SNDRV_PCM_FMTBIT_S24_LE | \
> + SNDRV_PCM_FMTBIT_S32_LE)
>
> static struct snd_soc_dai_driver sun4i_i2s_dai = {
> .capture = {
> @@ -1111,14 +1124,14 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = {
> .channels_min = 1,
> .channels_max = 8,
> .rates = SNDRV_PCM_RATE_8000_192000,
> - .formats = SUN4I_FORMATS,
> + .formats = SUN4I_FORMATS_ALL,
> },
> .playback = {
> .stream_name = "Playback",
> .channels_min = 1,
> .channels_max = 8,
> .rates = SNDRV_PCM_RATE_8000_192000,
> - .formats = SUN4I_FORMATS,
> + .formats = SUN4I_FORMATS_ALL,
> },
> .ops = &sun4i_i2s_dai_ops,
> .symmetric_rate = 1,
> @@ -1340,8 +1353,12 @@ static int sun4i_i2s_runtime_suspend(struct device *dev)
> return 0;
> }
>
> +#define SUN4I_FORMATS_A10 (SUN4I_FORMATS_ALL & ~SNDRV_PCM_FMTBIT_S32_LE)
> +#define SUN4I_FORMATS_H3 SUN4I_FORMATS_ALL
> +
> static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
> .has_reset = false,
> + .pcm_formats = SUN4I_FORMATS_A10,
> .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
> .sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
> .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
> @@ -1360,6 +1377,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
>
> static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
> .has_reset = true,
> + .pcm_formats = SUN4I_FORMATS_A10,
> .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG,
> .sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
> .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
> @@ -1383,6 +1401,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
> */
> static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
> .has_reset = true,
> + .pcm_formats = SUN4I_FORMATS_A10,
> .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
> .sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
> .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
> @@ -1401,6 +1420,7 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
>
> static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
> .has_reset = true,
> + .pcm_formats = SUN4I_FORMATS_H3,
> .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
> .sun4i_i2s_regmap = &sun8i_i2s_regmap_config,
> .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
> @@ -1419,6 +1439,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
>
> static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
> .has_reset = true,
> + .pcm_formats = SUN4I_FORMATS_H3,
> .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
> .sun4i_i2s_regmap = &sun4i_i2s_regmap_config,
> .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7),
> @@ -1437,6 +1458,7 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
>
> static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = {
> .has_reset = true,
> + .pcm_formats = SUN4I_FORMATS_H3,
> .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
> .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config,
> .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
> @@ -1455,6 +1477,7 @@ static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = {
>
> static const struct sun4i_i2s_quirks sun50i_r329_i2s_quirks = {
> .has_reset = true,
> + .pcm_formats = SUN4I_FORMATS_H3,
> .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
> .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config,
> .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
>
> ---
> base-commit: 13227c2baa6b345451128828c9c2b0ec3868bd0d
> change-id: 20240326-sunxi_s32-f2ab25b8e688
>
> Best regards,
>
On Wed, 03 Apr 2024 14:47:35 +1100, John Watts wrote:
> The I2S cores used in the H3 onwards support 32-bit sample rates.
> Support these by adding a per-variant PCM format list.
>
>
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: sunxi: sun4i-i2s: Support 32-bit audio formats
commit: 863f94ac5f4481a7c5665e8152d551701ac71bf3
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark