[PATCH 0/5] ASoC: rsnd: tidyup ADG
Hi Mark
------ for git-log ------ 8< ------ 8< ------ 8< ------
Renesas Sound has ADG for clock control. Basically it needs accurately divisible external input clock. But sometimes sometimes it doesn't have to be accurate for some reason.
We can use ADG clk_i for such case. It came from CPG as very high rate clock, but is not accurately divisible for 48kHz/44.1kHz rate, but enough for approximate rate.
This patch set support such use case.
------ extra info ------ 8< ------ 8< ------ 8< ------ 8< ------
Kuninori Morimoto (5): ASoC: rsnd: enable clk_i approximate rate usage ASoC: rsnd: setup clock-out only when all conditions are right ASoC: rsnd: tidyup brga/brgb default value ASoC: rsnd: remove default division of clock out ASoC: rsnd: setup BRGCKR/BRRA/BRRB on rsnd_adg_clk_control()
sound/soc/sh/rcar/adg.c | 68 +++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 13 deletions(-)
Basically Renesas sound ADG is assuming that it has accurately divisible input clock. But sometimes / some board might not have it. The clk_i from CPG is used for such case. It can't calculate accurate division, but can be used as approximate rate. This patch enable clk_i for such case.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Acked-by: Adnan Ali adnan.ali@bp.renesas.com Tested-by: Vincenzo De Michele vincenzo.michele@davinci.de Tested-by: Patrick Keil patrick.keil@conti-engineering.com --- sound/soc/sh/rcar/adg.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 1479d8d77dc7..55a51ea12144 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -492,6 +492,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) unsigned long req_Hz[ADG_HZ_SIZE]; int clkout_size; int i, req_size; + int approximate = 0; const char *parent_clk_name = NULL; const char * const *clkout_name; int brg_table[] = { @@ -538,6 +539,26 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) * rsnd_adg_ssi_clk_try_start() * rsnd_ssi_master_clk_start() */ + + /* + * [APPROXIMATE] + * + * clk_i (internal clock) can't create accurate rate, it will be approximate rate. + * + * <Note> + * + * clk_i needs x2 of required maximum rate. + * see + * - Minimum division of BRRA/BRRB + * - rsnd_ssi_clk_query() + * + * Sample Settings for TDM 8ch, 32bit width + * + * 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200 + * 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000 + * + * clock-frequency = <22579200 24576000>; + */ for_each_rsnd_clkin(clk, adg, i) { rate = clk_get_rate(clk);
@@ -545,6 +566,10 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) continue;
/* BRGA */ + + if (i == CLKI) + /* see [APPROXIMATE] */ + rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441]; if (!adg->brg_rate[ADG_HZ_441] && (0 == rate % 44100)) { div = 6; if (req_Hz[ADG_HZ_441]) @@ -556,10 +581,16 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) ckr |= brg_table[i] << 20; if (req_Hz[ADG_HZ_441]) parent_clk_name = __clk_get_name(clk); + if (i == CLKI) + approximate = 1; } }
/* BRGB */ + + if (i == CLKI) + /* see [APPROXIMATE] */ + rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48]; if (!adg->brg_rate[ADG_HZ_48] && (0 == rate % 48000)) { div = 6; if (req_Hz[ADG_HZ_48]) @@ -571,10 +602,15 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) ckr |= brg_table[i] << 16; if (req_Hz[ADG_HZ_48]) parent_clk_name = __clk_get_name(clk); + if (i == CLKI) + approximate = 1; } } }
+ if (approximate) + dev_info(dev, "It uses CLK_I as approximate rate"); + clkout_name = clkout_name_gen2; clkout_size = ARRAY_SIZE(clkout_name_gen2); if (rsnd_is_gen4(priv))
Current adg.c doesn't assume that requested clock out divide condition doesn't match. In such case, it will indicate strange message, and will register NULL clock, etc. It is just a DT setting miss, but is confusable. This patch check all conditions for it.
Reported-by: Vincenzo De Michele vincenzo.michele@davinci.de Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/adg.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 55a51ea12144..5528351c7535 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -608,6 +608,10 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) } }
+ if (!(adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48]) && + !(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441])) + goto rsnd_adg_get_clkout_end; + if (approximate) dev_info(dev, "It uses CLK_I as approximate rate");
default value for brga/brgb should be 0xff instead of 0x2. This patch tidyup it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/adg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 5528351c7535..fbe209b2430d 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -503,8 +503,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) };
ckr = 0; - brga = 2; /* default 1/6 */ - brgb = 2; /* default 1/6 */ + brga = 0xff; /* default */ + brgb = 0xff; /* default */
/* * ADG supports BRRA/BRRB output only
Current adg has default division for BRRA/BRRB, but it was created at very beginning of the driver implementation, and is now an unnecessary settings.
Because it has this default division, unexpected clockout might be selected. For example if it requests only 44.1kHz base clockout, unrequested 48kHz base clockout also will be selected.
This patch remove default division of clock out
Reported-by: Vincenzo De Michele vincenzo.michele@davinci.de Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/adg.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index fbe209b2430d..94e048614c81 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -486,7 +486,6 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) struct device_node *np = dev->of_node; struct property *prop; u32 ckr, brgx, brga, brgb; - u32 rate, div; u32 req_rate[ADG_HZ_SIZE] = {}; uint32_t count = 0; unsigned long req_Hz[ADG_HZ_SIZE]; @@ -560,6 +559,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) * clock-frequency = <22579200 24576000>; */ for_each_rsnd_clkin(clk, adg, i) { + u32 rate, div; + rate = clk_get_rate(clk);
if (0 == rate) /* not used */ @@ -570,10 +571,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) if (i == CLKI) /* see [APPROXIMATE] */ rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441]; - if (!adg->brg_rate[ADG_HZ_441] && (0 == rate % 44100)) { - div = 6; - if (req_Hz[ADG_HZ_441]) - div = rate / req_Hz[ADG_HZ_441]; + if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) { + div = rate / req_Hz[ADG_HZ_441]; brgx = rsnd_adg_calculate_brgx(div); if (BRRx_MASK(brgx) == brgx) { brga = brgx; @@ -591,10 +590,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) if (i == CLKI) /* see [APPROXIMATE] */ rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48]; - if (!adg->brg_rate[ADG_HZ_48] && (0 == rate % 48000)) { - div = 6; - if (req_Hz[ADG_HZ_48]) - div = rate / req_Hz[ADG_HZ_48]; + if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) { + div = rate / req_Hz[ADG_HZ_48]; brgx = rsnd_adg_calculate_brgx(div); if (BRRx_MASK(brgx) == brgx) { brgb = brgx;
Current adg.c will configure BRGCKR/BRRA/BRRB to output clock when it start sound. OTAH, rsnd_adg_clk_enable() will enables clk_a/b/c when driver was probed. But it is strange, these should be set in the same time. This patch fixup it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/adg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 94e048614c81..f0888cf31208 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -359,8 +359,6 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ckr = 0x80000000; /* BRGB output = 48kHz */
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr); - rsnd_mod_write(adg_mod, BRRA, adg->brga); - rsnd_mod_write(adg_mod, BRRB, adg->brgb);
dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n", (ckr) ? 'B' : 'A', @@ -373,9 +371,16 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct rsnd_mod *adg_mod = rsnd_mod_get(adg); struct clk *clk; int i;
+ if (enable) { + rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr); + rsnd_mod_write(adg_mod, BRRA, adg->brga); + rsnd_mod_write(adg_mod, BRRB, adg->brgb); + } + for_each_rsnd_clkin(clk, adg, i) { if (enable) { clk_prepare_enable(clk);
On Tue, Aug 22, 2023 at 11:50:10PM +0000, Kuninori Morimoto wrote:
------ for git-log ------ 8< ------ 8< ------ 8< ------
Renesas Sound has ADG for clock control. Basically it needs accurately divisible external input clock. But sometimes sometimes it doesn't have to be accurate for some reason.
We can use ADG clk_i for such case. It came from CPG as very high rate clock, but is not accurately divisible for 48kHz/44.1kHz rate, but enough for approximate rate.
This patch set support such use case.
------ extra info ------ 8< ------ 8< ------ 8< ------ 8< ------
When you put cut markers like this in your mail b4 thinks you want to hide that information, not hide the rest of the mail.
On Tue, 22 Aug 2023 23:50:10 +0000, Kuninori Morimoto wrote:
Kuninori Morimoto (5): ASoC: rsnd: enable clk_i approximate rate usage ASoC: rsnd: setup clock-out only when all conditions are right ASoC: rsnd: tidyup brga/brgb default value ASoC: rsnd: remove default division of clock out ASoC: rsnd: setup BRGCKR/BRRA/BRRB on rsnd_adg_clk_control()
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/5] ASoC: rsnd: enable clk_i approximate rate usage commit: bd4cee2fdf69b56c2bf3e7ec7c2e12b81e08005c [2/5] ASoC: rsnd: setup clock-out only when all conditions are right commit: d059cd40aea6deae716bc6588f24e7b6b421f822 [3/5] ASoC: rsnd: tidyup brga/brgb default value commit: 80d4984f38631b1157dd51214ccd3d2fc6d56fbb [4/5] ASoC: rsnd: remove default division of clock out commit: ab0233747f9cf6ba6c6d0c60c1e0e2533db00302 [5/5] ASoC: rsnd: setup BRGCKR/BRRA/BRRB on rsnd_adg_clk_control() commit: 4acdf9aedd5624aae9335d70a9324d5aaec4034d
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Kuninori Morimoto
-
Mark Brown