diff mbox series

[1/5] ASoC: rsnd: enable clk_i approximate rate usage

Message ID 87msyizlfd.wl-kuninori.morimoto.gx@renesas.com
State Accepted
Commit bd4cee2fdf69b56c2bf3e7ec7c2e12b81e08005c
Headers show
Series [1/5] ASoC: rsnd: enable clk_i approximate rate usage | expand

Commit Message

Kuninori Morimoto Aug. 22, 2023, 11:50 p.m. UTC
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 mbox series

Patch

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))