ASoC: rsnd: enable clk_i approximate rate usage
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tue, 22 Aug 2023 23:50:31 +0000 (23:50 +0000)
committerMark Brown <broonie@kernel.org>
Wed, 23 Aug 2023 12:53:25 +0000 (13:53 +0100)
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>
Link: https://lore.kernel.org/r/87msyizlfd.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sh/rcar/adg.c

index 0b8926600d900a688cae2f4942cf82e3ff8ad46d..c490d43aa18c2e6d10d211c43956ac0bce9f6945 100644 (file)
@@ -491,6 +491,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[] = {
@@ -537,6 +538,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);
 
@@ -544,6 +565,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])
@@ -555,10 +580,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])
@@ -570,10 +601,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))