diff mbox series

[v6,02/14] ASoC: sun4i-i2s: Change set_chan_cfg() params

Message ID 20201003141950.455829-3-peron.clem@gmail.com (mailing list archive)
State New, archived
Headers show
Series Add Allwinner H3/H5/H6/A64 HDMI audio | expand

Commit Message

Clément Péron Oct. 3, 2020, 2:19 p.m. UTC
As slots and slot_width can be set manually using set_tdm().
These values are then kept in sun4i_i2s struct.
So we need to check if these values are setted or not
in the struct.

Avoid to check for this logic in set_chan_cfg(). This will
duplicate the same check instead pass the required values
as params to set_chan_cfg().

This will also avoid a bug when we will enable 20/24bits support,
i2s->slot_width is not actually used in the lrck_period computation.

Suggested-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
---
 sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
 1 file changed, 14 insertions(+), 22 deletions(-)

Comments

Maxime Ripard Oct. 5, 2020, 12:13 p.m. UTC | #1
On Sat, Oct 03, 2020 at 04:19:38PM +0200, Clément Péron wrote:
> As slots and slot_width can be set manually using set_tdm().
> These values are then kept in sun4i_i2s struct.
> So we need to check if these values are setted or not
> in the struct.
> 
> Avoid to check for this logic in set_chan_cfg(). This will
> duplicate the same check instead pass the required values
> as params to set_chan_cfg().
> 
> This will also avoid a bug when we will enable 20/24bits support,
> i2s->slot_width is not actually used in the lrck_period computation.
> 
> Suggested-by: Samuel Holland <samuel@sholland.org>
> Signed-off-by: Clément Péron <peron.clem@gmail.com>
> ---
>  sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
>  1 file changed, 14 insertions(+), 22 deletions(-)
> 
> diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
> index c5ccd423e6d3..1f577dbc20a6 100644
> --- a/sound/soc/sunxi/sun4i-i2s.c
> +++ b/sound/soc/sunxi/sun4i-i2s.c
> @@ -177,8 +177,9 @@ struct sun4i_i2s_quirks {
>  	unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
>  	s8	(*get_sr)(const struct sun4i_i2s *, int);
>  	s8	(*get_wss)(const struct sun4i_i2s *, int);
> -	int	(*set_chan_cfg)(const struct sun4i_i2s *,
> -				const struct snd_pcm_hw_params *);
> +	int	(*set_chan_cfg)(const struct sun4i_i2s *i2s,
> +				unsigned int channels,	unsigned int slots,
> +				unsigned int slot_width);
>  	int	(*set_fmt)(const struct sun4i_i2s *, unsigned int);
>  };
>  
> @@ -414,10 +415,9 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
>  }
>  
>  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> -				  const struct snd_pcm_hw_params *params)
> +				  unsigned int channels, unsigned int slots,
> +				  unsigned int slot_width)
>  {
> -	unsigned int channels = params_channels(params);
> -
>  	/* Map the channels for playback and capture */
>  	regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
>  	regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
> @@ -434,15 +434,11 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>  }
>  
>  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> -				  const struct snd_pcm_hw_params *params)
> +				  unsigned int channels, unsigned int slots,
> +				  unsigned int slot_width)
>  {
> -	unsigned int channels = params_channels(params);
> -	unsigned int slots = channels;
>  	unsigned int lrck_period;
>  
> -	if (i2s->slots)
> -		slots = i2s->slots;
> -
>  	/* Map the channels for playback and capture */
>  	regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
>  	regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
> @@ -467,11 +463,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>  	case SND_SOC_DAIFMT_DSP_B:
>  	case SND_SOC_DAIFMT_LEFT_J:
>  	case SND_SOC_DAIFMT_RIGHT_J:
> -		lrck_period = params_physical_width(params) * slots;
> +		lrck_period = slot_width * slots;
>  		break;
>  
>  	case SND_SOC_DAIFMT_I2S:
> -		lrck_period = params_physical_width(params);
> +		lrck_period = slot_width;
>  		break;
>  
>  	default:
> @@ -490,15 +486,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>  }
>  
>  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> -				      const struct snd_pcm_hw_params *params)
> +				      unsigned int channels, unsigned int slots,
> +				      unsigned int slot_width)
>  {
> -	unsigned int channels = params_channels(params);
> -	unsigned int slots = channels;
>  	unsigned int lrck_period;
>  
> -	if (i2s->slots)
> -		slots = i2s->slots;
> -
>  	/* Map the channels for playback and capture */
>  	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
>  	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
> @@ -525,11 +517,11 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>  	case SND_SOC_DAIFMT_DSP_B:
>  	case SND_SOC_DAIFMT_LEFT_J:
>  	case SND_SOC_DAIFMT_RIGHT_J:
> -		lrck_period = params_physical_width(params) * slots;
> +		lrck_period = slot_width * slots;
>  		break;
>  
>  	case SND_SOC_DAIFMT_I2S:
> -		lrck_period = params_physical_width(params);
> +		lrck_period = slot_width;
>  		break;
>  
>  	default:
> @@ -565,7 +557,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
>  	if (i2s->slot_width)
>  		slot_width = i2s->slot_width;
>  
> -	ret = i2s->variant->set_chan_cfg(i2s, params);
> +	ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);

Isn't slots and slot_width set to 0 here ?

And therefore, wouldn't we set lrck_period to 0 if we're using any
format but I2S?

More importantly, I'm not really convinced this needs to be done, and it
introduces some side effects that are not explained.

Maxime
Clément Péron Oct. 5, 2020, 1:23 p.m. UTC | #2
Hi Maxime,

On Mon, 5 Oct 2020 at 14:13, Maxime Ripard <maxime@cerno.tech> wrote:
>
> On Sat, Oct 03, 2020 at 04:19:38PM +0200, Clément Péron wrote:
> > As slots and slot_width can be set manually using set_tdm().
> > These values are then kept in sun4i_i2s struct.
> > So we need to check if these values are setted or not
> > in the struct.
> >
> > Avoid to check for this logic in set_chan_cfg(). This will
> > duplicate the same check instead pass the required values
> > as params to set_chan_cfg().
> >
> > This will also avoid a bug when we will enable 20/24bits support,
> > i2s->slot_width is not actually used in the lrck_period computation.
> >
> > Suggested-by: Samuel Holland <samuel@sholland.org>
> > Signed-off-by: Clément Péron <peron.clem@gmail.com>
> > ---
> >  sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
> >  1 file changed, 14 insertions(+), 22 deletions(-)
> >
> > diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
> > index c5ccd423e6d3..1f577dbc20a6 100644
> > --- a/sound/soc/sunxi/sun4i-i2s.c
> > +++ b/sound/soc/sunxi/sun4i-i2s.c
> > @@ -177,8 +177,9 @@ struct sun4i_i2s_quirks {
> >       unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
> >       s8      (*get_sr)(const struct sun4i_i2s *, int);
> >       s8      (*get_wss)(const struct sun4i_i2s *, int);
> > -     int     (*set_chan_cfg)(const struct sun4i_i2s *,
> > -                             const struct snd_pcm_hw_params *);
> > +     int     (*set_chan_cfg)(const struct sun4i_i2s *i2s,
> > +                             unsigned int channels,  unsigned int slots,
> > +                             unsigned int slot_width);
> >       int     (*set_fmt)(const struct sun4i_i2s *, unsigned int);
> >  };
> >
> > @@ -414,10 +415,9 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
> >  }
> >
> >  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > -                               const struct snd_pcm_hw_params *params)
> > +                               unsigned int channels, unsigned int slots,
> > +                               unsigned int slot_width)
> >  {
> > -     unsigned int channels = params_channels(params);
> > -
> >       /* Map the channels for playback and capture */
> >       regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> >       regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
> > @@ -434,15 +434,11 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >  }
> >
> >  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > -                               const struct snd_pcm_hw_params *params)
> > +                               unsigned int channels, unsigned int slots,
> > +                               unsigned int slot_width)
> >  {
> > -     unsigned int channels = params_channels(params);
> > -     unsigned int slots = channels;
> >       unsigned int lrck_period;
> >
> > -     if (i2s->slots)
> > -             slots = i2s->slots;
> > -
> >       /* Map the channels for playback and capture */
> >       regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> >       regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
> > @@ -467,11 +463,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >       case SND_SOC_DAIFMT_DSP_B:
> >       case SND_SOC_DAIFMT_LEFT_J:
> >       case SND_SOC_DAIFMT_RIGHT_J:
> > -             lrck_period = params_physical_width(params) * slots;
> > +             lrck_period = slot_width * slots;
> >               break;
> >
> >       case SND_SOC_DAIFMT_I2S:
> > -             lrck_period = params_physical_width(params);
> > +             lrck_period = slot_width;
> >               break;
> >
> >       default:
> > @@ -490,15 +486,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >  }
> >
> >  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > -                                   const struct snd_pcm_hw_params *params)
> > +                                   unsigned int channels, unsigned int slots,
> > +                                   unsigned int slot_width)
> >  {
> > -     unsigned int channels = params_channels(params);
> > -     unsigned int slots = channels;
> >       unsigned int lrck_period;
> >
> > -     if (i2s->slots)
> > -             slots = i2s->slots;
> > -
> >       /* Map the channels for playback and capture */
> >       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
> >       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
> > @@ -525,11 +517,11 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >       case SND_SOC_DAIFMT_DSP_B:
> >       case SND_SOC_DAIFMT_LEFT_J:
> >       case SND_SOC_DAIFMT_RIGHT_J:
> > -             lrck_period = params_physical_width(params) * slots;
> > +             lrck_period = slot_width * slots;
> >               break;
> >
> >       case SND_SOC_DAIFMT_I2S:
> > -             lrck_period = params_physical_width(params);
> > +             lrck_period = slot_width;
> >               break;
> >
> >       default:
> > @@ -565,7 +557,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
> >       if (i2s->slot_width)
> >               slot_width = i2s->slot_width;
> >
> > -     ret = i2s->variant->set_chan_cfg(i2s, params);
> > +     ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
>
> Isn't slots and slot_width set to 0 here ?

No, there is still a check before calling the set_cfg function.

  unsigned int slot_width = params_physical_width(params);
  unsigned int channels = params_channels(params);
  unsigned int slots = channels;

  if (i2s->slots)
  slots = i2s->slots;

  if (i2s->slot_width)
  slot_width = i2s->slot_width;

ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);

So slot_width will be equal to params_physical_width(params);
like before

Clement

>
> And therefore, wouldn't we set lrck_period to 0 if we're using any
> format but I2S?
>
> More importantly, I'm not really convinced this needs to be done, and it
> introduces some side effects that are not explained.
>
> Maxime
Samuel Holland Oct. 6, 2020, 5:03 a.m. UTC | #3
On 10/5/20 7:13 AM, Maxime Ripard wrote:
> On Sat, Oct 03, 2020 at 04:19:38PM +0200, Clément Péron wrote:
>> As slots and slot_width can be set manually using set_tdm().
>> These values are then kept in sun4i_i2s struct.
>> So we need to check if these values are setted or not
>> in the struct.
>>
>> Avoid to check for this logic in set_chan_cfg(). This will
>> duplicate the same check instead pass the required values
>> as params to set_chan_cfg().
>>
>> This will also avoid a bug when we will enable 20/24bits support,
>> i2s->slot_width is not actually used in the lrck_period computation.
>>
>> Suggested-by: Samuel Holland <samuel@sholland.org>
>> Signed-off-by: Clément Péron <peron.clem@gmail.com>
>> ---
>>  sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
>>  1 file changed, 14 insertions(+), 22 deletions(-)
>>
>> diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
>> index c5ccd423e6d3..1f577dbc20a6 100644
>> --- a/sound/soc/sunxi/sun4i-i2s.c
>> +++ b/sound/soc/sunxi/sun4i-i2s.c
>> @@ -177,8 +177,9 @@ struct sun4i_i2s_quirks {
>>  	unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
>>  	s8	(*get_sr)(const struct sun4i_i2s *, int);
>>  	s8	(*get_wss)(const struct sun4i_i2s *, int);
>> -	int	(*set_chan_cfg)(const struct sun4i_i2s *,
>> -				const struct snd_pcm_hw_params *);
>> +	int	(*set_chan_cfg)(const struct sun4i_i2s *i2s,
>> +				unsigned int channels,	unsigned int slots,
>> +				unsigned int slot_width);
>>  	int	(*set_fmt)(const struct sun4i_i2s *, unsigned int);
>>  };
>>  
>> @@ -414,10 +415,9 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
>>  }
>>  
>>  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>> -				  const struct snd_pcm_hw_params *params)
>> +				  unsigned int channels, unsigned int slots,
>> +				  unsigned int slot_width)
>>  {
>> -	unsigned int channels = params_channels(params);
>> -
>>  	/* Map the channels for playback and capture */
>>  	regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
>>  	regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
>> @@ -434,15 +434,11 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>  }
>>  
>>  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>> -				  const struct snd_pcm_hw_params *params)
>> +				  unsigned int channels, unsigned int slots,
>> +				  unsigned int slot_width)
>>  {
>> -	unsigned int channels = params_channels(params);
>> -	unsigned int slots = channels;
>>  	unsigned int lrck_period;
>>  
>> -	if (i2s->slots)
>> -		slots = i2s->slots;
>> -
>>  	/* Map the channels for playback and capture */
>>  	regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
>>  	regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
>> @@ -467,11 +463,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>  	case SND_SOC_DAIFMT_DSP_B:
>>  	case SND_SOC_DAIFMT_LEFT_J:
>>  	case SND_SOC_DAIFMT_RIGHT_J:
>> -		lrck_period = params_physical_width(params) * slots;
>> +		lrck_period = slot_width * slots;
>>  		break;
>>  
>>  	case SND_SOC_DAIFMT_I2S:
>> -		lrck_period = params_physical_width(params);
>> +		lrck_period = slot_width;
>>  		break;
>>  
>>  	default:
>> @@ -490,15 +486,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>  }
>>  
>>  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>> -				      const struct snd_pcm_hw_params *params)
>> +				      unsigned int channels, unsigned int slots,
>> +				      unsigned int slot_width)
>>  {
>> -	unsigned int channels = params_channels(params);
>> -	unsigned int slots = channels;
>>  	unsigned int lrck_period;
>>  
>> -	if (i2s->slots)
>> -		slots = i2s->slots;
>> -
>>  	/* Map the channels for playback and capture */
>>  	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
>>  	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
>> @@ -525,11 +517,11 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>  	case SND_SOC_DAIFMT_DSP_B:
>>  	case SND_SOC_DAIFMT_LEFT_J:
>>  	case SND_SOC_DAIFMT_RIGHT_J:
>> -		lrck_period = params_physical_width(params) * slots;
>> +		lrck_period = slot_width * slots;
>>  		break;
>>  
>>  	case SND_SOC_DAIFMT_I2S:
>> -		lrck_period = params_physical_width(params);
>> +		lrck_period = slot_width;
>>  		break;
>>  
>>  	default:
>> @@ -565,7 +557,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
>>  	if (i2s->slot_width)
>>  		slot_width = i2s->slot_width;
>>  
>> -	ret = i2s->variant->set_chan_cfg(i2s, params);
>> +	ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
> 
> Isn't slots and slot_width set to 0 here ?
> 
> And therefore, wouldn't we set lrck_period to 0 if we're using any
> format but I2S?
> 
> More importantly, I'm not really convinced this needs to be done, and it
> introduces some side effects that are not explained.

If I set dai-tdm-slot-width = <32> and start a stream using S16_LE,
currently we would calculate BCLK for 32-bit slots, but program
lrck_period for 16-bit slots, making the sample rate double what we
expected. That sounds like a bug to me. (Because of that, as Chen-Yu
mentioned in reply to v5, this should be the first patch in the series.)

Could you be more specific what side effects you are referring to?

> Maxime

Cheers,
Samuel
Maxime Ripard Oct. 12, 2020, 12:15 p.m. UTC | #4
Hi,

On Mon, Oct 05, 2020 at 03:23:12PM +0200, Clément Péron wrote:
> On Mon, 5 Oct 2020 at 14:13, Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > On Sat, Oct 03, 2020 at 04:19:38PM +0200, Clément Péron wrote:
> > > As slots and slot_width can be set manually using set_tdm().
> > > These values are then kept in sun4i_i2s struct.
> > > So we need to check if these values are setted or not
> > > in the struct.
> > >
> > > Avoid to check for this logic in set_chan_cfg(). This will
> > > duplicate the same check instead pass the required values
> > > as params to set_chan_cfg().
> > >
> > > This will also avoid a bug when we will enable 20/24bits support,
> > > i2s->slot_width is not actually used in the lrck_period computation.
> > >
> > > Suggested-by: Samuel Holland <samuel@sholland.org>
> > > Signed-off-by: Clément Péron <peron.clem@gmail.com>
> > > ---
> > >  sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
> > >  1 file changed, 14 insertions(+), 22 deletions(-)
> > >
> > > diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
> > > index c5ccd423e6d3..1f577dbc20a6 100644
> > > --- a/sound/soc/sunxi/sun4i-i2s.c
> > > +++ b/sound/soc/sunxi/sun4i-i2s.c
> > > @@ -177,8 +177,9 @@ struct sun4i_i2s_quirks {
> > >       unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
> > >       s8      (*get_sr)(const struct sun4i_i2s *, int);
> > >       s8      (*get_wss)(const struct sun4i_i2s *, int);
> > > -     int     (*set_chan_cfg)(const struct sun4i_i2s *,
> > > -                             const struct snd_pcm_hw_params *);
> > > +     int     (*set_chan_cfg)(const struct sun4i_i2s *i2s,
> > > +                             unsigned int channels,  unsigned int slots,
> > > +                             unsigned int slot_width);
> > >       int     (*set_fmt)(const struct sun4i_i2s *, unsigned int);
> > >  };
> > >
> > > @@ -414,10 +415,9 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
> > >  }
> > >
> > >  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > > -                               const struct snd_pcm_hw_params *params)
> > > +                               unsigned int channels, unsigned int slots,
> > > +                               unsigned int slot_width)
> > >  {
> > > -     unsigned int channels = params_channels(params);
> > > -
> > >       /* Map the channels for playback and capture */
> > >       regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> > >       regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
> > > @@ -434,15 +434,11 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > >  }
> > >
> > >  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > > -                               const struct snd_pcm_hw_params *params)
> > > +                               unsigned int channels, unsigned int slots,
> > > +                               unsigned int slot_width)
> > >  {
> > > -     unsigned int channels = params_channels(params);
> > > -     unsigned int slots = channels;
> > >       unsigned int lrck_period;
> > >
> > > -     if (i2s->slots)
> > > -             slots = i2s->slots;
> > > -
> > >       /* Map the channels for playback and capture */
> > >       regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> > >       regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
> > > @@ -467,11 +463,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > >       case SND_SOC_DAIFMT_DSP_B:
> > >       case SND_SOC_DAIFMT_LEFT_J:
> > >       case SND_SOC_DAIFMT_RIGHT_J:
> > > -             lrck_period = params_physical_width(params) * slots;
> > > +             lrck_period = slot_width * slots;
> > >               break;
> > >
> > >       case SND_SOC_DAIFMT_I2S:
> > > -             lrck_period = params_physical_width(params);
> > > +             lrck_period = slot_width;
> > >               break;
> > >
> > >       default:
> > > @@ -490,15 +486,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > >  }
> > >
> > >  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > > -                                   const struct snd_pcm_hw_params *params)
> > > +                                   unsigned int channels, unsigned int slots,
> > > +                                   unsigned int slot_width)
> > >  {
> > > -     unsigned int channels = params_channels(params);
> > > -     unsigned int slots = channels;
> > >       unsigned int lrck_period;
> > >
> > > -     if (i2s->slots)
> > > -             slots = i2s->slots;
> > > -
> > >       /* Map the channels for playback and capture */
> > >       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
> > >       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
> > > @@ -525,11 +517,11 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> > >       case SND_SOC_DAIFMT_DSP_B:
> > >       case SND_SOC_DAIFMT_LEFT_J:
> > >       case SND_SOC_DAIFMT_RIGHT_J:
> > > -             lrck_period = params_physical_width(params) * slots;
> > > +             lrck_period = slot_width * slots;
> > >               break;
> > >
> > >       case SND_SOC_DAIFMT_I2S:
> > > -             lrck_period = params_physical_width(params);
> > > +             lrck_period = slot_width;
> > >               break;
> > >
> > >       default:
> > > @@ -565,7 +557,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
> > >       if (i2s->slot_width)
> > >               slot_width = i2s->slot_width;
> > >
> > > -     ret = i2s->variant->set_chan_cfg(i2s, params);
> > > +     ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
> >
> > Isn't slots and slot_width set to 0 here ?
> 
> No, there is still a check before calling the set_cfg function.
> 
>   unsigned int slot_width = params_physical_width(params);
>   unsigned int channels = params_channels(params);
>   unsigned int slots = channels;
> 
>   if (i2s->slots)
>   slots = i2s->slots;
> 
>   if (i2s->slot_width)
>   slot_width = i2s->slot_width;
> 
> ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
> 
> So slot_width will be equal to params_physical_width(params);
> like before

Still, it's not obvious what slots and slot_width are going to be set to
in a non-TDM setup where that doesn't really make much sense.

I assume you want to reduce the boilerplate, then we can make an helper
to get the frame size and the number of channels / slots if needed

Maxime
Maxime Ripard Oct. 12, 2020, 12:20 p.m. UTC | #5
On Tue, Oct 06, 2020 at 12:03:14AM -0500, Samuel Holland wrote:
> On 10/5/20 7:13 AM, Maxime Ripard wrote:
> > On Sat, Oct 03, 2020 at 04:19:38PM +0200, Clément Péron wrote:
> >> As slots and slot_width can be set manually using set_tdm().
> >> These values are then kept in sun4i_i2s struct.
> >> So we need to check if these values are setted or not
> >> in the struct.
> >>
> >> Avoid to check for this logic in set_chan_cfg(). This will
> >> duplicate the same check instead pass the required values
> >> as params to set_chan_cfg().
> >>
> >> This will also avoid a bug when we will enable 20/24bits support,
> >> i2s->slot_width is not actually used in the lrck_period computation.
> >>
> >> Suggested-by: Samuel Holland <samuel@sholland.org>
> >> Signed-off-by: Clément Péron <peron.clem@gmail.com>
> >> ---
> >>  sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
> >>  1 file changed, 14 insertions(+), 22 deletions(-)
> >>
> >> diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
> >> index c5ccd423e6d3..1f577dbc20a6 100644
> >> --- a/sound/soc/sunxi/sun4i-i2s.c
> >> +++ b/sound/soc/sunxi/sun4i-i2s.c
> >> @@ -177,8 +177,9 @@ struct sun4i_i2s_quirks {
> >>  	unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
> >>  	s8	(*get_sr)(const struct sun4i_i2s *, int);
> >>  	s8	(*get_wss)(const struct sun4i_i2s *, int);
> >> -	int	(*set_chan_cfg)(const struct sun4i_i2s *,
> >> -				const struct snd_pcm_hw_params *);
> >> +	int	(*set_chan_cfg)(const struct sun4i_i2s *i2s,
> >> +				unsigned int channels,	unsigned int slots,
> >> +				unsigned int slot_width);
> >>  	int	(*set_fmt)(const struct sun4i_i2s *, unsigned int);
> >>  };
> >>  
> >> @@ -414,10 +415,9 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
> >>  }
> >>  
> >>  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >> -				  const struct snd_pcm_hw_params *params)
> >> +				  unsigned int channels, unsigned int slots,
> >> +				  unsigned int slot_width)
> >>  {
> >> -	unsigned int channels = params_channels(params);
> >> -
> >>  	/* Map the channels for playback and capture */
> >>  	regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> >>  	regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
> >> @@ -434,15 +434,11 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>  }
> >>  
> >>  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >> -				  const struct snd_pcm_hw_params *params)
> >> +				  unsigned int channels, unsigned int slots,
> >> +				  unsigned int slot_width)
> >>  {
> >> -	unsigned int channels = params_channels(params);
> >> -	unsigned int slots = channels;
> >>  	unsigned int lrck_period;
> >>  
> >> -	if (i2s->slots)
> >> -		slots = i2s->slots;
> >> -
> >>  	/* Map the channels for playback and capture */
> >>  	regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> >>  	regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
> >> @@ -467,11 +463,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>  	case SND_SOC_DAIFMT_DSP_B:
> >>  	case SND_SOC_DAIFMT_LEFT_J:
> >>  	case SND_SOC_DAIFMT_RIGHT_J:
> >> -		lrck_period = params_physical_width(params) * slots;
> >> +		lrck_period = slot_width * slots;
> >>  		break;
> >>  
> >>  	case SND_SOC_DAIFMT_I2S:
> >> -		lrck_period = params_physical_width(params);
> >> +		lrck_period = slot_width;
> >>  		break;
> >>  
> >>  	default:
> >> @@ -490,15 +486,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>  }
> >>  
> >>  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >> -				      const struct snd_pcm_hw_params *params)
> >> +				      unsigned int channels, unsigned int slots,
> >> +				      unsigned int slot_width)
> >>  {
> >> -	unsigned int channels = params_channels(params);
> >> -	unsigned int slots = channels;
> >>  	unsigned int lrck_period;
> >>  
> >> -	if (i2s->slots)
> >> -		slots = i2s->slots;
> >> -
> >>  	/* Map the channels for playback and capture */
> >>  	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
> >>  	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
> >> @@ -525,11 +517,11 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>  	case SND_SOC_DAIFMT_DSP_B:
> >>  	case SND_SOC_DAIFMT_LEFT_J:
> >>  	case SND_SOC_DAIFMT_RIGHT_J:
> >> -		lrck_period = params_physical_width(params) * slots;
> >> +		lrck_period = slot_width * slots;
> >>  		break;
> >>  
> >>  	case SND_SOC_DAIFMT_I2S:
> >> -		lrck_period = params_physical_width(params);
> >> +		lrck_period = slot_width;
> >>  		break;
> >>  
> >>  	default:
> >> @@ -565,7 +557,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
> >>  	if (i2s->slot_width)
> >>  		slot_width = i2s->slot_width;
> >>  
> >> -	ret = i2s->variant->set_chan_cfg(i2s, params);
> >> +	ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
> > 
> > Isn't slots and slot_width set to 0 here ?
> > 
> > And therefore, wouldn't we set lrck_period to 0 if we're using any
> > format but I2S?
> > 
> > More importantly, I'm not really convinced this needs to be done, and it
> > introduces some side effects that are not explained.
> 
> If I set dai-tdm-slot-width = <32> and start a stream using S16_LE,
> currently we would calculate BCLK for 32-bit slots, but program
> lrck_period for 16-bit slots, making the sample rate double what we
> expected. That sounds like a bug to me. (Because of that, as Chen-Yu
> mentioned in reply to v5, this should be the first patch in the series.)

I'm not denying that there's a bug though here :)

You've spent way more time than I did with this driver recently, so I
definitely take your word for it.

> Could you be more specific what side effects you are referring to?

I don't really like the change of semantics associated to the new
prototype, and it becomes less obvious what we're supposed to do with
slots and slot_width. Like, those are very TDM-y terms, are we supposed
to honour them when running in I2S, or should we just ignore them?

Maxime
Samuel Holland Oct. 13, 2020, 1:15 a.m. UTC | #6
On 10/12/20 7:15 AM, Maxime Ripard wrote:
> Hi,
> 
> On Mon, Oct 05, 2020 at 03:23:12PM +0200, Clément Péron wrote:
>> On Mon, 5 Oct 2020 at 14:13, Maxime Ripard <maxime@cerno.tech> wrote:
>>>
>>> On Sat, Oct 03, 2020 at 04:19:38PM +0200, Clément Péron wrote:
>>>> As slots and slot_width can be set manually using set_tdm().
>>>> These values are then kept in sun4i_i2s struct.
>>>> So we need to check if these values are setted or not
>>>> in the struct.
>>>>
>>>> Avoid to check for this logic in set_chan_cfg(). This will
>>>> duplicate the same check instead pass the required values
>>>> as params to set_chan_cfg().
>>>>
>>>> This will also avoid a bug when we will enable 20/24bits support,
>>>> i2s->slot_width is not actually used in the lrck_period computation.
>>>>
>>>> Suggested-by: Samuel Holland <samuel@sholland.org>
>>>> Signed-off-by: Clément Péron <peron.clem@gmail.com>
>>>> ---
>>>>  sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
>>>>  1 file changed, 14 insertions(+), 22 deletions(-)
>>>>
>>>> diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
>>>> index c5ccd423e6d3..1f577dbc20a6 100644
>>>> --- a/sound/soc/sunxi/sun4i-i2s.c
>>>> +++ b/sound/soc/sunxi/sun4i-i2s.c
>>>> @@ -177,8 +177,9 @@ struct sun4i_i2s_quirks {
>>>>       unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
>>>>       s8      (*get_sr)(const struct sun4i_i2s *, int);
>>>>       s8      (*get_wss)(const struct sun4i_i2s *, int);
>>>> -     int     (*set_chan_cfg)(const struct sun4i_i2s *,
>>>> -                             const struct snd_pcm_hw_params *);
>>>> +     int     (*set_chan_cfg)(const struct sun4i_i2s *i2s,
>>>> +                             unsigned int channels,  unsigned int slots,
>>>> +                             unsigned int slot_width);
>>>>       int     (*set_fmt)(const struct sun4i_i2s *, unsigned int);
>>>>  };
>>>>
>>>> @@ -414,10 +415,9 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
>>>>  }
>>>>
>>>>  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>>> -                               const struct snd_pcm_hw_params *params)
>>>> +                               unsigned int channels, unsigned int slots,
>>>> +                               unsigned int slot_width)
>>>>  {
>>>> -     unsigned int channels = params_channels(params);
>>>> -
>>>>       /* Map the channels for playback and capture */
>>>>       regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
>>>>       regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
>>>> @@ -434,15 +434,11 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>>>  }
>>>>
>>>>  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>>> -                               const struct snd_pcm_hw_params *params)
>>>> +                               unsigned int channels, unsigned int slots,
>>>> +                               unsigned int slot_width)
>>>>  {
>>>> -     unsigned int channels = params_channels(params);
>>>> -     unsigned int slots = channels;
>>>>       unsigned int lrck_period;
>>>>
>>>> -     if (i2s->slots)
>>>> -             slots = i2s->slots;
>>>> -
>>>>       /* Map the channels for playback and capture */
>>>>       regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
>>>>       regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
>>>> @@ -467,11 +463,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>>>       case SND_SOC_DAIFMT_DSP_B:
>>>>       case SND_SOC_DAIFMT_LEFT_J:
>>>>       case SND_SOC_DAIFMT_RIGHT_J:
>>>> -             lrck_period = params_physical_width(params) * slots;
>>>> +             lrck_period = slot_width * slots;
>>>>               break;
>>>>
>>>>       case SND_SOC_DAIFMT_I2S:
>>>> -             lrck_period = params_physical_width(params);
>>>> +             lrck_period = slot_width;
>>>>               break;
>>>>
>>>>       default:
>>>> @@ -490,15 +486,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>>>  }
>>>>
>>>>  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>>> -                                   const struct snd_pcm_hw_params *params)
>>>> +                                   unsigned int channels, unsigned int slots,
>>>> +                                   unsigned int slot_width)
>>>>  {
>>>> -     unsigned int channels = params_channels(params);
>>>> -     unsigned int slots = channels;
>>>>       unsigned int lrck_period;
>>>>
>>>> -     if (i2s->slots)
>>>> -             slots = i2s->slots;
>>>> -
>>>>       /* Map the channels for playback and capture */
>>>>       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
>>>>       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
>>>> @@ -525,11 +517,11 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
>>>>       case SND_SOC_DAIFMT_DSP_B:
>>>>       case SND_SOC_DAIFMT_LEFT_J:
>>>>       case SND_SOC_DAIFMT_RIGHT_J:
>>>> -             lrck_period = params_physical_width(params) * slots;
>>>> +             lrck_period = slot_width * slots;
>>>>               break;
>>>>
>>>>       case SND_SOC_DAIFMT_I2S:
>>>> -             lrck_period = params_physical_width(params);
>>>> +             lrck_period = slot_width;
>>>>               break;
>>>>
>>>>       default:
>>>> @@ -565,7 +557,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
>>>>       if (i2s->slot_width)
>>>>               slot_width = i2s->slot_width;
>>>>
>>>> -     ret = i2s->variant->set_chan_cfg(i2s, params);
>>>> +     ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
>>>
>>> Isn't slots and slot_width set to 0 here ?
>>
>> No, there is still a check before calling the set_cfg function.
>>
>>   unsigned int slot_width = params_physical_width(params);
>>   unsigned int channels = params_channels(params);
>>   unsigned int slots = channels;
>>
>>   if (i2s->slots)
>>   slots = i2s->slots;
>>
>>   if (i2s->slot_width)
>>   slot_width = i2s->slot_width;
>>
>> ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
>>
>> So slot_width will be equal to params_physical_width(params);
>> like before
> 
> Still, it's not obvious what slots and slot_width are going to be set to
> in a non-TDM setup where that doesn't really make much sense.

My understanding is:

"slots" is channels per frame + padding slots, regardless of format.
"slot_width" is bits per sample + padding bits, regardless of format.

Some formats may require or prohibit certain padding, but that has no
effect on the definitions.

That seems clear to me? At least that's what I implemented (and you
acked) in sun8i-codec.

> I assume you want to reduce the boilerplate, then we can make an helper
> to get the frame size and the number of channels / slots if needed

What would you name the return values, if not "slots" and "slot_width"?
"channels" and "word_size" would be inaccurate, because those terms
refer to the values without padding.

> Maxime

Cheers,
Samuel
Maxime Ripard Oct. 19, 2020, 10:24 a.m. UTC | #7
Hi Samuel,

On Mon, Oct 12, 2020 at 08:15:30PM -0500, Samuel Holland wrote:
> On 10/12/20 7:15 AM, Maxime Ripard wrote:
> > Hi,
> > 
> > On Mon, Oct 05, 2020 at 03:23:12PM +0200, Clément Péron wrote:
> >> On Mon, 5 Oct 2020 at 14:13, Maxime Ripard <maxime@cerno.tech> wrote:
> >>>
> >>> On Sat, Oct 03, 2020 at 04:19:38PM +0200, Clément Péron wrote:
> >>>> As slots and slot_width can be set manually using set_tdm().
> >>>> These values are then kept in sun4i_i2s struct.
> >>>> So we need to check if these values are setted or not
> >>>> in the struct.
> >>>>
> >>>> Avoid to check for this logic in set_chan_cfg(). This will
> >>>> duplicate the same check instead pass the required values
> >>>> as params to set_chan_cfg().
> >>>>
> >>>> This will also avoid a bug when we will enable 20/24bits support,
> >>>> i2s->slot_width is not actually used in the lrck_period computation.
> >>>>
> >>>> Suggested-by: Samuel Holland <samuel@sholland.org>
> >>>> Signed-off-by: Clément Péron <peron.clem@gmail.com>
> >>>> ---
> >>>>  sound/soc/sunxi/sun4i-i2s.c | 36 ++++++++++++++----------------------
> >>>>  1 file changed, 14 insertions(+), 22 deletions(-)
> >>>>
> >>>> diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
> >>>> index c5ccd423e6d3..1f577dbc20a6 100644
> >>>> --- a/sound/soc/sunxi/sun4i-i2s.c
> >>>> +++ b/sound/soc/sunxi/sun4i-i2s.c
> >>>> @@ -177,8 +177,9 @@ struct sun4i_i2s_quirks {
> >>>>       unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
> >>>>       s8      (*get_sr)(const struct sun4i_i2s *, int);
> >>>>       s8      (*get_wss)(const struct sun4i_i2s *, int);
> >>>> -     int     (*set_chan_cfg)(const struct sun4i_i2s *,
> >>>> -                             const struct snd_pcm_hw_params *);
> >>>> +     int     (*set_chan_cfg)(const struct sun4i_i2s *i2s,
> >>>> +                             unsigned int channels,  unsigned int slots,
> >>>> +                             unsigned int slot_width);
> >>>>       int     (*set_fmt)(const struct sun4i_i2s *, unsigned int);
> >>>>  };
> >>>>
> >>>> @@ -414,10 +415,9 @@ static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
> >>>>  }
> >>>>
> >>>>  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>>> -                               const struct snd_pcm_hw_params *params)
> >>>> +                               unsigned int channels, unsigned int slots,
> >>>> +                               unsigned int slot_width)
> >>>>  {
> >>>> -     unsigned int channels = params_channels(params);
> >>>> -
> >>>>       /* Map the channels for playback and capture */
> >>>>       regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> >>>>       regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
> >>>> @@ -434,15 +434,11 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>>>  }
> >>>>
> >>>>  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>>> -                               const struct snd_pcm_hw_params *params)
> >>>> +                               unsigned int channels, unsigned int slots,
> >>>> +                               unsigned int slot_width)
> >>>>  {
> >>>> -     unsigned int channels = params_channels(params);
> >>>> -     unsigned int slots = channels;
> >>>>       unsigned int lrck_period;
> >>>>
> >>>> -     if (i2s->slots)
> >>>> -             slots = i2s->slots;
> >>>> -
> >>>>       /* Map the channels for playback and capture */
> >>>>       regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
> >>>>       regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
> >>>> @@ -467,11 +463,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>>>       case SND_SOC_DAIFMT_DSP_B:
> >>>>       case SND_SOC_DAIFMT_LEFT_J:
> >>>>       case SND_SOC_DAIFMT_RIGHT_J:
> >>>> -             lrck_period = params_physical_width(params) * slots;
> >>>> +             lrck_period = slot_width * slots;
> >>>>               break;
> >>>>
> >>>>       case SND_SOC_DAIFMT_I2S:
> >>>> -             lrck_period = params_physical_width(params);
> >>>> +             lrck_period = slot_width;
> >>>>               break;
> >>>>
> >>>>       default:
> >>>> @@ -490,15 +486,11 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>>>  }
> >>>>
> >>>>  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>>> -                                   const struct snd_pcm_hw_params *params)
> >>>> +                                   unsigned int channels, unsigned int slots,
> >>>> +                                   unsigned int slot_width)
> >>>>  {
> >>>> -     unsigned int channels = params_channels(params);
> >>>> -     unsigned int slots = channels;
> >>>>       unsigned int lrck_period;
> >>>>
> >>>> -     if (i2s->slots)
> >>>> -             slots = i2s->slots;
> >>>> -
> >>>>       /* Map the channels for playback and capture */
> >>>>       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
> >>>>       regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
> >>>> @@ -525,11 +517,11 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
> >>>>       case SND_SOC_DAIFMT_DSP_B:
> >>>>       case SND_SOC_DAIFMT_LEFT_J:
> >>>>       case SND_SOC_DAIFMT_RIGHT_J:
> >>>> -             lrck_period = params_physical_width(params) * slots;
> >>>> +             lrck_period = slot_width * slots;
> >>>>               break;
> >>>>
> >>>>       case SND_SOC_DAIFMT_I2S:
> >>>> -             lrck_period = params_physical_width(params);
> >>>> +             lrck_period = slot_width;
> >>>>               break;
> >>>>
> >>>>       default:
> >>>> @@ -565,7 +557,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
> >>>>       if (i2s->slot_width)
> >>>>               slot_width = i2s->slot_width;
> >>>>
> >>>> -     ret = i2s->variant->set_chan_cfg(i2s, params);
> >>>> +     ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
> >>>
> >>> Isn't slots and slot_width set to 0 here ?
> >>
> >> No, there is still a check before calling the set_cfg function.
> >>
> >>   unsigned int slot_width = params_physical_width(params);
> >>   unsigned int channels = params_channels(params);
> >>   unsigned int slots = channels;
> >>
> >>   if (i2s->slots)
> >>   slots = i2s->slots;
> >>
> >>   if (i2s->slot_width)
> >>   slot_width = i2s->slot_width;
> >>
> >> ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
> >>
> >> So slot_width will be equal to params_physical_width(params);
> >> like before
> > 
> > Still, it's not obvious what slots and slot_width are going to be set to
> > in a non-TDM setup where that doesn't really make much sense.
> 
> My understanding is:
> 
> "slots" is channels per frame + padding slots, regardless of format.
> "slot_width" is bits per sample + padding bits, regardless of format.
> 
> Some formats may require or prohibit certain padding, but that has no
> effect on the definitions.
> 
> That seems clear to me? At least that's what I implemented (and you
> acked) in sun8i-codec.

Yeah I guess you're right. I'd still like at least a comment on top of
the function making that clear so that no-one's confused

Maxime
diff mbox series

Patch

diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index c5ccd423e6d3..1f577dbc20a6 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -177,8 +177,9 @@  struct sun4i_i2s_quirks {
 	unsigned long (*get_bclk_parent_rate)(const struct sun4i_i2s *);
 	s8	(*get_sr)(const struct sun4i_i2s *, int);
 	s8	(*get_wss)(const struct sun4i_i2s *, int);
-	int	(*set_chan_cfg)(const struct sun4i_i2s *,
-				const struct snd_pcm_hw_params *);
+	int	(*set_chan_cfg)(const struct sun4i_i2s *i2s,
+				unsigned int channels,	unsigned int slots,
+				unsigned int slot_width);
 	int	(*set_fmt)(const struct sun4i_i2s *, unsigned int);
 };
 
@@ -414,10 +415,9 @@  static s8 sun8i_i2s_get_sr_wss(const struct sun4i_i2s *i2s, int width)
 }
 
 static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
-				  const struct snd_pcm_hw_params *params)
+				  unsigned int channels, unsigned int slots,
+				  unsigned int slot_width)
 {
-	unsigned int channels = params_channels(params);
-
 	/* Map the channels for playback and capture */
 	regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
 	regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
@@ -434,15 +434,11 @@  static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
 }
 
 static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
-				  const struct snd_pcm_hw_params *params)
+				  unsigned int channels, unsigned int slots,
+				  unsigned int slot_width)
 {
-	unsigned int channels = params_channels(params);
-	unsigned int slots = channels;
 	unsigned int lrck_period;
 
-	if (i2s->slots)
-		slots = i2s->slots;
-
 	/* Map the channels for playback and capture */
 	regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
 	regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
@@ -467,11 +463,11 @@  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
 	case SND_SOC_DAIFMT_DSP_B:
 	case SND_SOC_DAIFMT_LEFT_J:
 	case SND_SOC_DAIFMT_RIGHT_J:
-		lrck_period = params_physical_width(params) * slots;
+		lrck_period = slot_width * slots;
 		break;
 
 	case SND_SOC_DAIFMT_I2S:
-		lrck_period = params_physical_width(params);
+		lrck_period = slot_width;
 		break;
 
 	default:
@@ -490,15 +486,11 @@  static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
 }
 
 static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
-				      const struct snd_pcm_hw_params *params)
+				      unsigned int channels, unsigned int slots,
+				      unsigned int slot_width)
 {
-	unsigned int channels = params_channels(params);
-	unsigned int slots = channels;
 	unsigned int lrck_period;
 
-	if (i2s->slots)
-		slots = i2s->slots;
-
 	/* Map the channels for playback and capture */
 	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98);
 	regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210);
@@ -525,11 +517,11 @@  static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
 	case SND_SOC_DAIFMT_DSP_B:
 	case SND_SOC_DAIFMT_LEFT_J:
 	case SND_SOC_DAIFMT_RIGHT_J:
-		lrck_period = params_physical_width(params) * slots;
+		lrck_period = slot_width * slots;
 		break;
 
 	case SND_SOC_DAIFMT_I2S:
-		lrck_period = params_physical_width(params);
+		lrck_period = slot_width;
 		break;
 
 	default:
@@ -565,7 +557,7 @@  static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
 	if (i2s->slot_width)
 		slot_width = i2s->slot_width;
 
-	ret = i2s->variant->set_chan_cfg(i2s, params);
+	ret = i2s->variant->set_chan_cfg(i2s, channels, slots, slot_width);
 	if (ret < 0) {
 		dev_err(dai->dev, "Invalid channel configuration\n");
 		return ret;