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]