1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

ASoC: rsnd: adjust convert rate in 1%

Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

Renesas Synchronous SRC Mode has HW limitation to be used in 1% rate
difference, but driver didn't care it. This patch-set adjust to it.

Link: https://lore.kernel.org/r/87o6zi32ry.wl-kuninori.morimoto.gx@renesas.com
This commit is contained in:
Mark Brown 2025-02-06 16:16:34 +00:00
commit b9cb90a5bf
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
4 changed files with 95 additions and 39 deletions

View file

@ -1770,20 +1770,6 @@ int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io)
return 1; return 1;
} }
int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io)
{
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct device *dev = rsnd_priv_to_dev(priv);
if (!runtime) {
dev_warn(dev, "Can't update kctrl when idle\n");
return 0;
}
return 1;
}
struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg) struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg)
{ {
cfg->cfg.val = cfg->val; cfg->cfg.val = cfg->val;

View file

@ -742,7 +742,6 @@ struct rsnd_kctrl_cfg_s {
#define rsnd_kctrl_vals(x) ((x).val) /* = (x).cfg.val[0] */ #define rsnd_kctrl_vals(x) ((x).val) /* = (x).cfg.val[0] */
int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io); int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io);
int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io);
struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg); struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg);
struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg); struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg);
int rsnd_kctrl_new(struct rsnd_mod *mod, int rsnd_kctrl_new(struct rsnd_mod *mod,

View file

@ -35,6 +35,7 @@ struct rsnd_src {
struct rsnd_mod *dma; struct rsnd_mod *dma;
struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ struct rsnd_kctrl_cfg_s sen; /* sync convert enable */
struct rsnd_kctrl_cfg_s sync; /* sync convert */ struct rsnd_kctrl_cfg_s sync; /* sync convert */
u32 current_sync_rate;
int irq; int irq;
}; };
@ -100,7 +101,7 @@ static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io,
if (!rsnd_src_sync_is_enabled(mod)) if (!rsnd_src_sync_is_enabled(mod))
return rsnd_io_converted_rate(io); return rsnd_io_converted_rate(io);
convert_rate = src->sync.val; convert_rate = src->current_sync_rate;
if (!convert_rate) if (!convert_rate)
convert_rate = rsnd_io_converted_rate(io); 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, static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
struct rsnd_mod *mod) struct rsnd_mod *mod)
{ {
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
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 rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
int is_play = rsnd_io_is_play(io); int is_play = rsnd_io_is_play(io);
int use_src = 0; int use_src = 0;
u32 fin, fout; u32 fin, fout;
u32 ifscr, fsrate, adinr; u32 ifscr, adinr;
u32 cr, route; u32 cr, route;
u32 i_busif, o_busif, tmp; u32 i_busif, o_busif, tmp;
const u32 *bsdsr_table; 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; adinr = rsnd_get_adinr_bit(mod, io) | chan;
/* /*
* SRC_IFSCR / SRC_IFSVR * SRC_IFSCR
*/
ifscr = 0;
fsrate = 0;
if (use_src) {
u64 n;
ifscr = 1;
n = (u64)0x0400000 * fin;
do_div(n, fout);
fsrate = n;
}
/*
* SRC_SRCCR / SRC_ROUTE_MODE0 * SRC_SRCCR / SRC_ROUTE_MODE0
*/ */
ifscr = 0;
cr = 0x00011110; cr = 0x00011110;
route = 0x0; route = 0x0;
if (use_src) { if (use_src) {
route = 0x1; route = 0x1;
ifscr = 0x1;
if (rsnd_src_sync_is_enabled(mod)) { if (rsnd_src_sync_is_enabled(mod)) {
cr |= 0x1; 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_SRCIR, 1); /* initialize */
rsnd_mod_write(mod, SRC_ADINR, adinr); rsnd_mod_write(mod, SRC_ADINR, adinr);
rsnd_mod_write(mod, SRC_IFSCR, ifscr); 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_SRCCR, cr);
rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]); rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]);
rsnd_mod_write(mod, SRC_BSISR, bsisr_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); rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
/* update SRC_IFSVR */
rsnd_src_set_convert_rate(io, mod);
return; return;
convert_rate_err: convert_rate_err:
@ -467,7 +519,8 @@ static int rsnd_src_init(struct rsnd_mod *mod,
int ret; int ret;
/* reset sync convert_rate */ /* reset sync convert_rate */
src->sync.val = 0; src->sync.val =
src->current_sync_rate = 0;
ret = rsnd_mod_power_on(mod); ret = rsnd_mod_power_on(mod);
if (ret < 0) if (ret < 0)
@ -475,7 +528,7 @@ static int rsnd_src_init(struct rsnd_mod *mod,
rsnd_src_activation(mod); rsnd_src_activation(mod);
rsnd_src_set_convert_rate(io, mod); rsnd_src_init_convert_rate(io, mod);
rsnd_src_status_clear(mod); rsnd_src_status_clear(mod);
@ -493,7 +546,8 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
rsnd_mod_power_off(mod); rsnd_mod_power_off(mod);
/* reset sync convert_rate */ /* reset sync convert_rate */
src->sync.val = 0; src->sync.val =
src->current_sync_rate = 0;
return 0; return 0;
} }
@ -531,6 +585,22 @@ static irqreturn_t rsnd_src_interrupt(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int rsnd_src_kctrl_accept_runtime(struct rsnd_dai_stream *io)
{
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
if (!runtime) {
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct device *dev = rsnd_priv_to_dev(priv);
dev_warn(dev, "\"SRC Out Rate\" can use during running\n");
return 0;
}
return 1;
}
static int rsnd_src_probe_(struct rsnd_mod *mod, static int rsnd_src_probe_(struct rsnd_mod *mod,
struct rsnd_dai_stream *io, struct rsnd_dai_stream *io,
struct rsnd_priv *priv) struct rsnd_priv *priv)
@ -585,7 +655,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
"SRC Out Rate Switch" : "SRC Out Rate Switch" :
"SRC In Rate Switch", "SRC In Rate Switch",
rsnd_kctrl_accept_anytime, rsnd_kctrl_accept_anytime,
rsnd_src_set_convert_rate, rsnd_src_init_convert_rate,
&src->sen, 1); &src->sen, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -594,7 +664,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod,
rsnd_io_is_play(io) ? rsnd_io_is_play(io) ?
"SRC Out Rate" : "SRC Out Rate" :
"SRC In Rate", "SRC In Rate",
rsnd_kctrl_accept_runtime, rsnd_src_kctrl_accept_runtime,
rsnd_src_set_convert_rate, rsnd_src_set_convert_rate,
&src->sync, 192000); &src->sync, 192000);

View file

@ -336,7 +336,8 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
return 0; return 0;
rate_err: rate_err:
dev_err(dev, "unsupported clock rate\n"); dev_err(dev, "unsupported clock rate (%d)\n", rate);
return ret; return ret;
} }