[PATCH v3 01/19] ASoC: sun4i-i2s: Add support for H6 I2S

Samuel Holland samuel at sholland.org
Sun Sep 20 14:39:15 EDT 2020


On 9/20/20 1:07 PM, Clément Péron wrote:
> From: Jernej Skrabec <jernej.skrabec at siol.net>
> 
> H6 I2S is very similar to that in H3, except it supports up to 16
> channels.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec at siol.net>
> Signed-off-by: Marcus Cooper <codekipper at gmail.com>
> Signed-off-by: Clément Péron <peron.clem at gmail.com>
> ---
>  sound/soc/sunxi/sun4i-i2s.c | 218 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 218 insertions(+)
> 
> diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
> index f23ff29e7c1d..348057464bed 100644
> --- a/sound/soc/sunxi/sun4i-i2s.c
> +++ b/sound/soc/sunxi/sun4i-i2s.c
...
> @@ -699,6 +770,102 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
>  	return 0;
>  }
>  
> +static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
> +				     unsigned int fmt)
> +{
> +	u32 mode, val;
> +	u8 offset;
> +
> +	/* DAI clock polarity */
> +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +	case SND_SOC_DAIFMT_IB_IF:
> +		/* Invert both clocks */
> +		val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED |
> +		      SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
> +		break;
> +	case SND_SOC_DAIFMT_IB_NF:
> +		/* Invert bit clock */
> +		val = SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED;
> +		break;
> +	case SND_SOC_DAIFMT_NB_IF:
> +		/* Invert frame clock */
> +		val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
> +		break;
> +	case SND_SOC_DAIFMT_NB_NF:
> +		val = 0;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}

Maxime's testing that showed LRCK inversion was necessary was done on the H6. So
in addition to dropping the patch that removed the LRCK inversion for other
sun8i variants, you need to re-add it to this patch for the H6 variant.

Cheers,
Samuel

> +
> +	regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT0_REG,
> +			   SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK |
> +			   SUN8I_I2S_FMT0_BCLK_POLARITY_MASK,
> +			   val);
> +
> +	/* DAI Mode */
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_DSP_A:
> +		mode = SUN8I_I2S_CTRL_MODE_PCM;
> +		offset = 1;
> +		break;
> +
> +	case SND_SOC_DAIFMT_DSP_B:
> +		mode = SUN8I_I2S_CTRL_MODE_PCM;
> +		offset = 0;
> +		break;
> +
> +	case SND_SOC_DAIFMT_I2S:
> +		mode = SUN8I_I2S_CTRL_MODE_LEFT;
> +		offset = 1;
> +		break;
> +
> +	case SND_SOC_DAIFMT_LEFT_J:
> +		mode = SUN8I_I2S_CTRL_MODE_LEFT;
> +		offset = 0;
> +		break;
> +
> +	case SND_SOC_DAIFMT_RIGHT_J:
> +		mode = SUN8I_I2S_CTRL_MODE_RIGHT;
> +		offset = 0;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
> +			   SUN8I_I2S_CTRL_MODE_MASK, mode);
> +	regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
> +			   SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK,
> +			   SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset));
> +	regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG,
> +			   SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK,
> +			   SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset));
> +
> +	/* DAI clock master masks */
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		/* BCLK and LRCLK master */
> +		val = SUN8I_I2S_CTRL_BCLK_OUT |	SUN8I_I2S_CTRL_LRCK_OUT;
> +		break;
> +
> +	case SND_SOC_DAIFMT_CBM_CFM:
> +		/* BCLK and LRCLK slave */
> +		val = 0;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
> +			   SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT,
> +			   val);
> +
> +	return 0;
> +}
> +
>  static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>  {
>  	struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
...



More information about the linux-arm-kernel mailing list