RE: [PATCH 3/3] ASoC: rsnd: adjust convert rate limitation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



Hello Morimoto-san,

> From: Kuninori Morimoto, Sent: Tuesday, February 4, 2025 10:42 AM
> 
> Current rsnd driver supports Synchronous SRC Mode, but HW allow to update
> rate only within 1% from current rate. Adjust to it.
> 
> Becially, this feature is used to fine-tune subtle difference that occur
> during sampling rate conversion in SRC. So, it should be called within 1%
> margin of rate difference.
> 
> If there was difference over 1%, it will apply with 1% increments by using
> loop without indicating error message.
> 
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@xxxxxxxxxxx>

Thank you for the patch!

Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx>

Without this patch, an overrun error occurred on a specific situation.
However, I applied this patch, the error didn't occur.
So,

Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx>

Best regards,
Yoshihiro Shimoda

> ---
>  sound/soc/renesas/rcar/src.c | 98 ++++++++++++++++++++++++++++--------
>  1 file changed, 76 insertions(+), 22 deletions(-)
> 
> diff --git a/sound/soc/renesas/rcar/src.c b/sound/soc/renesas/rcar/src.c
> index 3099180297722..7d73b183bda68 100644
> --- a/sound/soc/renesas/rcar/src.c
> +++ b/sound/soc/renesas/rcar/src.c
> @@ -35,6 +35,7 @@ struct rsnd_src {
>  	struct rsnd_mod *dma;
>  	struct rsnd_kctrl_cfg_s sen;  /* sync convert enable */
>  	struct rsnd_kctrl_cfg_s sync; /* sync convert */
> +	u32 current_sync_rate;
>  	int irq;
>  };
> 
> @@ -100,7 +101,7 @@ static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
>  	if (!rsnd_src_sync_is_enabled(mod))
>  		return rsnd_io_converted_rate(io);
> 
> -	convert_rate = src->sync.val;
> +	convert_rate = src->current_sync_rate;
> 
>  	if (!convert_rate)
>  		convert_rate = rsnd_io_converted_rate(io);
> @@ -201,13 +202,73 @@ static const u32 chan222222[] = {
>  static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
>  				      struct rsnd_mod *mod)
>  {
> +	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
>  	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
> -	struct device *dev = rsnd_priv_to_dev(priv);
> +	struct rsnd_src *src = rsnd_mod_to_src(mod);
> +	u32 fin, fout, new_rate;
> +	int inc, cnt, rate;
> +	u64 base, val;
> +
> +	if (!runtime)
> +		return;
> +
> +	if (!rsnd_src_sync_is_enabled(mod))
> +		return;
> +
> +	fin	= rsnd_src_get_in_rate(priv, io);
> +	fout	= rsnd_src_get_out_rate(priv, io);
> +
> +	new_rate = src->sync.val;
> +
> +	if (!new_rate)
> +		new_rate = fout;
> +
> +	/* Do nothing if no diff */
> +	if (new_rate == src->current_sync_rate)
> +		return;
> +
> +	/*
> +	 * SRCm_IFSVR::INTIFS can change within 1%
> +	 * see
> +	 *	SRCm_IFSVR::INTIFS Note
> +	 */
> +	inc = fout / 100;
> +	cnt = abs(new_rate - fout) / inc;
> +	if (fout > new_rate)
> +		inc *= -1;
> +
> +	/*
> +	 * After start running SRC, we can update only SRC_IFSVR
> +	 * for Synchronous Mode
> +	 */
> +	base = (u64)0x0400000 * fin;
> +	rate  = fout;
> +	for (int i = 0; i < cnt; i++) {
> +		val   = base;
> +		rate += inc;
> +		do_div(val, rate);
> +
> +		rsnd_mod_write(mod, SRC_IFSVR, val);
> +	}
> +	val   = base;
> +	do_div(val, new_rate);
> +
> +	rsnd_mod_write(mod, SRC_IFSVR, val);
> +
> +	/* update current_sync_rate */
> +	src->current_sync_rate = new_rate;
> +}
> +
> +static void rsnd_src_init_convert_rate(struct rsnd_dai_stream *io,
> +				       struct rsnd_mod *mod)
> +{
>  	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
> +	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
> +	struct device *dev = rsnd_priv_to_dev(priv);
>  	int is_play = rsnd_io_is_play(io);
>  	int use_src = 0;
>  	u32 fin, fout;
> -	u32 ifscr, fsrate, adinr;
> +	u32 ifscr, adinr;
>  	u32 cr, route;
>  	u32 i_busif, o_busif, tmp;
>  	const u32 *bsdsr_table;
> @@ -245,26 +306,15 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
>  	adinr = rsnd_get_adinr_bit(mod, io) | chan;
> 
>  	/*
> -	 * SRC_IFSCR / SRC_IFSVR
> -	 */
> -	ifscr = 0;
> -	fsrate = 0;
> -	if (use_src) {
> -		u64 n;
> -
> -		ifscr = 1;
> -		n = (u64)0x0400000 * fin;
> -		do_div(n, fout);
> -		fsrate = n;
> -	}
> -
> -	/*
> +	 * SRC_IFSCR
>  	 * SRC_SRCCR / SRC_ROUTE_MODE0
>  	 */
> +	ifscr	= 0;
>  	cr	= 0x00011110;
>  	route	= 0x0;
>  	if (use_src) {
>  		route	= 0x1;
> +		ifscr	= 0x1;
> 
>  		if (rsnd_src_sync_is_enabled(mod)) {
>  			cr |= 0x1;
> @@ -335,7 +385,6 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
>  	rsnd_mod_write(mod, SRC_SRCIR, 1);	/* initialize */
>  	rsnd_mod_write(mod, SRC_ADINR, adinr);
>  	rsnd_mod_write(mod, SRC_IFSCR, ifscr);
> -	rsnd_mod_write(mod, SRC_IFSVR, fsrate);
>  	rsnd_mod_write(mod, SRC_SRCCR, cr);
>  	rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]);
>  	rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]);
> @@ -348,6 +397,9 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
> 
>  	rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
> 
> +	/* update SRC_IFSVR */
> +	rsnd_src_set_convert_rate(io, mod);
> +
>  	return;
> 
>  convert_rate_err:
> @@ -467,7 +519,8 @@ static int rsnd_src_init(struct rsnd_mod *mod,
>  	int ret;
> 
>  	/* reset sync convert_rate */
> -	src->sync.val = 0;
> +	src->sync.val		=
> +	src->current_sync_rate	= 0;
> 
>  	ret = rsnd_mod_power_on(mod);
>  	if (ret < 0)
> @@ -475,7 +528,7 @@ static int rsnd_src_init(struct rsnd_mod *mod,
> 
>  	rsnd_src_activation(mod);
> 
> -	rsnd_src_set_convert_rate(io, mod);
> +	rsnd_src_init_convert_rate(io, mod);
> 
>  	rsnd_src_status_clear(mod);
> 
> @@ -493,7 +546,8 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
>  	rsnd_mod_power_off(mod);
> 
>  	/* reset sync convert_rate */
> -	src->sync.val = 0;
> +	src->sync.val		=
> +	src->current_sync_rate	= 0;
> 
>  	return 0;
>  }
> @@ -601,7 +655,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
>  			       "SRC Out Rate Switch" :
>  			       "SRC In Rate Switch",
>  			       rsnd_kctrl_accept_anytime,
> -			       rsnd_src_set_convert_rate,
> +			       rsnd_src_init_convert_rate,
>  			       &src->sen, 1);
>  	if (ret < 0)
>  		return ret;
> --
> 2.43.0






[Index of Archives]     [Pulseaudio]     [Linux Audio Users]     [ALSA Devel]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]

  Powered by Linux