ASoC: rsnd: add R-Car Gen4 Sound support
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Wed, 1 Feb 2023 02:02:22 +0000 (02:02 +0000)
committerMark Brown <broonie@kernel.org>
Wed, 1 Feb 2023 11:43:57 +0000 (11:43 +0000)
This patch is tested on V4H White Hawk + ARD-AUDIO-DA7212

Signed-off-by: Linh Phung <linh.phung.jy@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87o7qe5ej5.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/dma.c
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/ssiu.c

index 00df32b..7bc4421 100644 (file)
@@ -57,6 +57,10 @@ struct rsnd_adg {
             i++)
 #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
 
+static const char * const clkin_name_gen4[] = {
+       [CLKA]  = "clkin",
+};
+
 static const char * const clkin_name_gen2[] = {
        [CLKA]  = "clk_a",
        [CLKB]  = "clk_b",
@@ -435,6 +439,10 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
 
        clkin_name = clkin_name_gen2;
        clkin_size = ARRAY_SIZE(clkin_name_gen2);
+       if (rsnd_is_gen4(priv)) {
+               clkin_name = clkin_name_gen4;
+               clkin_size = ARRAY_SIZE(clkin_name_gen4);
+       }
 
        for (i = 0; i < clkin_size; i++) {
                clk = devm_clk_get(dev, clkin_name[i]);
@@ -568,6 +576,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
 
        clkout_name = clkout_name_gen2;
        clkout_size = ARRAY_SIZE(clkout_name_gen2);
+       if (rsnd_is_gen4(priv))
+               clkout_size = 1; /* reuse clkout_name_gen2[] */
 
        /*
         * ADG supports BRRA/BRRB output only.
index 3de81af..a9125c1 100644 (file)
@@ -102,6 +102,7 @@ static const struct of_device_id rsnd_of_match[] = {
        { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
        { .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 },
        { .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 },
+       { .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 },
        /* Special Handling */
        { .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) },
        {},
@@ -1467,7 +1468,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
        if (is_graph) {
                for_each_endpoint_of_node(dai_node, dai_np) {
                        __rsnd_dai_probe(priv, dai_np, dai_i);
-                       if (rsnd_is_gen3(priv)) {
+                       if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
                                rdai = rsnd_rdai_get(priv, dai_i);
 
                                rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
@@ -1478,7 +1479,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
        } else {
                for_each_child_of_node(dai_node, dai_np) {
                        __rsnd_dai_probe(priv, dai_np, dai_i);
-                       if (rsnd_is_gen3(priv)) {
+                       if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
                                rdai = rsnd_rdai_get(priv, dai_i);
 
                                rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
index 9aca5ff..1c494e5 100644 (file)
@@ -653,6 +653,36 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
                dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
 }
 
+/*
+ *     Gen4 DMA read/write register offset
+ *
+ *     ex) R-Car V4H case
+ *               mod           / SYS-DMAC in   / SYS-DMAC out
+ *     SSI_SDMC: 0xec400000    / 0xec400000    / 0xec400000
+ */
+#define RDMA_SSI_SDMC(addr, i) (addr + (0x8000 * i))
+static dma_addr_t
+rsnd_gen4_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
+                  int is_play, int is_from)
+{
+       struct rsnd_priv *priv = rsnd_io_to_priv(io);
+       phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_GEN4_SDMC);
+       int id = rsnd_mod_id(mod);
+       int busif = rsnd_mod_id_sub(mod);
+
+       /*
+        * SSI0 only is supported
+        */
+       if (id != 0) {
+               struct device *dev = rsnd_priv_to_dev(priv);
+
+               dev_err(dev, "This driver doesn't support non SSI0");
+               return -EINVAL;
+       }
+
+       return RDMA_SSI_SDMC(addr, busif);
+}
+
 static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
                                struct rsnd_mod *mod,
                                int is_play, int is_from)
@@ -667,6 +697,8 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
         */
        if (rsnd_is_gen1(priv))
                return 0;
+       else if (rsnd_is_gen4(priv))
+               return rsnd_gen4_dma_addr(io, mod, is_play, is_from);
        else
                return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
 }
@@ -891,6 +923,10 @@ int rsnd_dma_probe(struct rsnd_priv *priv)
                return 0; /* it will be PIO mode */
        }
 
+       /* for Gen4 doesn't have DMA-pp */
+       if (rsnd_is_gen4(priv))
+               goto audmapp_end;
+
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp");
        if (!res) {
                dev_err(dev, "lack of audmapp in DT\n");
@@ -902,7 +938,7 @@ int rsnd_dma_probe(struct rsnd_priv *priv)
        dmac->ppbase = devm_ioremap_resource(dev, res);
        if (IS_ERR(dmac->ppbase))
                return PTR_ERR(dmac->ppbase);
-
+audmapp_end:
        priv->dma = dmac;
 
        /* dummy mem mod for debug */
index 925565b..86bdecc 100644 (file)
@@ -216,6 +216,74 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
 }
 
 /*
+ *             Gen4
+ */
+static int rsnd_gen4_probe(struct rsnd_priv *priv)
+{
+       static const struct rsnd_regmap_field_conf conf_ssiu[] = {
+               RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0,     0x850),
+               RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2,     0x858),
+               RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4,     0x890),
+               RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6,     0x898),
+               RSND_GEN_S_REG(SSI_SYS_STATUS0,         0x840),
+               RSND_GEN_S_REG(SSI_SYS_STATUS2,         0x848),
+               RSND_GEN_S_REG(SSI_SYS_STATUS4,         0x880),
+               RSND_GEN_S_REG(SSI_SYS_STATUS6,         0x888),
+
+               RSND_GEN_S_REG(SSI_BUSIF0_MODE,         0x0),
+               RSND_GEN_S_REG(SSI_BUSIF0_ADINR,        0x4),
+               RSND_GEN_S_REG(SSI_BUSIF0_DALIGN,       0x8),
+               RSND_GEN_S_REG(SSI_BUSIF1_MODE,         0x20),
+               RSND_GEN_S_REG(SSI_BUSIF1_ADINR,        0x24),
+               RSND_GEN_S_REG(SSI_BUSIF1_DALIGN,       0x28),
+               RSND_GEN_S_REG(SSI_BUSIF2_MODE,         0x40),
+               RSND_GEN_S_REG(SSI_BUSIF2_ADINR,        0x44),
+               RSND_GEN_S_REG(SSI_BUSIF2_DALIGN,       0x48),
+               RSND_GEN_S_REG(SSI_BUSIF3_MODE,         0x60),
+               RSND_GEN_S_REG(SSI_BUSIF3_ADINR,        0x64),
+               RSND_GEN_S_REG(SSI_BUSIF3_DALIGN,       0x68),
+               RSND_GEN_S_REG(SSI_BUSIF4_MODE,         0x500),
+               RSND_GEN_S_REG(SSI_BUSIF4_ADINR,        0x504),
+               RSND_GEN_S_REG(SSI_BUSIF4_DALIGN,       0x508),
+               RSND_GEN_S_REG(SSI_BUSIF5_MODE,         0x520),
+               RSND_GEN_S_REG(SSI_BUSIF5_ADINR,        0x524),
+               RSND_GEN_S_REG(SSI_BUSIF5_DALIGN,       0x528),
+               RSND_GEN_S_REG(SSI_BUSIF6_MODE,         0x540),
+               RSND_GEN_S_REG(SSI_BUSIF6_ADINR,        0x544),
+               RSND_GEN_S_REG(SSI_BUSIF6_DALIGN,       0x548),
+               RSND_GEN_S_REG(SSI_BUSIF7_MODE,         0x560),
+               RSND_GEN_S_REG(SSI_BUSIF7_ADINR,        0x564),
+               RSND_GEN_S_REG(SSI_BUSIF7_DALIGN,       0x568),
+               RSND_GEN_S_REG(SSI_CTRL,                0x010),
+               RSND_GEN_S_REG(SSI_INT_ENABLE,          0x018),
+               RSND_GEN_S_REG(SSI_MODE,                0x00c),
+               RSND_GEN_S_REG(SSI_MODE2,               0xa0c),
+       };
+       static const struct rsnd_regmap_field_conf conf_adg[] = {
+               RSND_GEN_S_REG(BRRA,                    0x00),
+               RSND_GEN_S_REG(BRRB,                    0x04),
+               RSND_GEN_S_REG(BRGCKR,                  0x08),
+               RSND_GEN_S_REG(AUDIO_CLK_SEL0,          0x0c),
+       };
+       static const struct rsnd_regmap_field_conf conf_ssi[] = {
+               RSND_GEN_S_REG(SSICR,                   0x00),
+               RSND_GEN_S_REG(SSISR,                   0x04),
+               RSND_GEN_S_REG(SSITDR,                  0x08),
+               RSND_GEN_S_REG(SSIRDR,                  0x0c),
+               RSND_GEN_S_REG(SSIWSR,                  0x20),
+       };
+       static const struct rsnd_regmap_field_conf conf_sdmc[] = {
+               RSND_GEN_M_REG(SSI_BUSIF,               0x0, 0x8000),
+       };
+       int ret_adg  = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_ADG,  "adg",  conf_adg);
+       int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSIU, "ssiu", conf_ssiu);
+       int ret_ssi  = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSI,  "ssi",  conf_ssi);
+       int ret_sdmc = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SDMC, "sdmc", conf_sdmc);
+
+       return ret_adg | ret_ssiu | ret_ssi | ret_sdmc;
+}
+
+/*
  *             Gen2
  */
 static int rsnd_gen2_probe(struct rsnd_priv *priv)
@@ -484,6 +552,8 @@ int rsnd_gen_probe(struct rsnd_priv *priv)
        else if (rsnd_is_gen2(priv) ||
                 rsnd_is_gen3(priv))
                ret = rsnd_gen2_probe(priv);
+       else if (rsnd_is_gen4(priv))
+               ret = rsnd_gen4_probe(priv);
 
        if (ret < 0)
                dev_err(dev, "unknown generation R-Car sound device\n");
index 3e1184f..239705d 100644 (file)
 #define RSND_GEN2_SSIU 2
 #define RSND_GEN2_SSI  3
 
+#define RSND_GEN4_ADG  0
+#define RSND_GEN4_SSIU 1
+#define RSND_GEN4_SSI  2
+#define RSND_GEN4_SDMC 3
+
 #define RSND_BASE_MAX  4
 
 /*
@@ -197,6 +202,7 @@ enum rsnd_reg {
        SSI_SYS_INT_ENABLE5,
        SSI_SYS_INT_ENABLE6,
        SSI_SYS_INT_ENABLE7,
+       SSI_BUSIF,
        HDMI0_SEL,
        HDMI1_SEL,
        SSI9_BUSIF0_MODE,
@@ -629,6 +635,7 @@ struct rsnd_priv {
 #define RSND_GEN1      (1 << 0)
 #define RSND_GEN2      (2 << 0)
 #define RSND_GEN3      (3 << 0)
+#define RSND_GEN4      (4 << 0)
 #define RSND_SOC_MASK  (0xFF << 4)
 #define RSND_SOC_E     (1 << 4) /* E1/E2/E3 */
 
@@ -703,6 +710,7 @@ struct rsnd_priv {
 #define rsnd_is_gen1(priv)     (((priv)->flags & RSND_GEN_MASK) == RSND_GEN1)
 #define rsnd_is_gen2(priv)     (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2)
 #define rsnd_is_gen3(priv)     (((priv)->flags & RSND_GEN_MASK) == RSND_GEN3)
+#define rsnd_is_gen4(priv)     (((priv)->flags & RSND_GEN_MASK) == RSND_GEN4)
 #define rsnd_is_e3(priv)       (((priv)->flags & \
                                        (RSND_GEN_MASK | RSND_SOC_MASK)) == \
                                        (RSND_GEN3 | RSND_SOC_E))
index 281bc20..17bd8cc 100644 (file)
@@ -29,8 +29,8 @@ struct rsnd_ssiu {
             i++)
 
 /*
- *     SSI     Gen2            Gen3
- *     0       BUSIF0-3        BUSIF0-7
+ *     SSI     Gen2            Gen3            Gen4
+ *     0       BUSIF0-3        BUSIF0-7        BUSIF0-7
  *     1       BUSIF0-3        BUSIF0-7
  *     2       BUSIF0-3        BUSIF0-7
  *     3       BUSIF0          BUSIF0-7
@@ -40,10 +40,11 @@ struct rsnd_ssiu {
  *     7       BUSIF0          BUSIF0
  *     8       BUSIF0          BUSIF0
  *     9       BUSIF0-3        BUSIF0-7
- *     total   22              52
+ *     total   22              52              8
  */
 static const int gen2_id[] = { 0, 4,  8, 12, 13, 14, 15, 16, 17, 18 };
 static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 };
+static const int gen4_id[] = { 0 };
 
 /* enable busif buffer over/under run interrupt. */
 #define rsnd_ssiu_busif_err_irq_enable(mod)  rsnd_ssiu_busif_err_irq_ctrl(mod, 1)
@@ -152,6 +153,10 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
        /* clear status */
        rsnd_ssiu_busif_err_status_clear(mod);
 
+       /* Gen4 doesn't have SSI_MODE */
+       if (rsnd_is_gen4(priv))
+               goto ssi_mode_setting_end;
+
        /*
         * SSI_MODE0
         */
@@ -206,6 +211,7 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
        rsnd_mod_bset(mod, SSI_MODE1, 0x0013001f, val1);
        rsnd_mod_bset(mod, SSI_MODE2, 0x00000017, val2);
 
+ssi_mode_setting_end:
        /*
         * Enable busif buffer over/under run interrupt.
         * It will be handled from ssi.c
@@ -553,6 +559,9 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
                } else if (rsnd_is_gen3(priv)) {
                        list    = gen3_id;
                        nr      = ARRAY_SIZE(gen3_id);
+               } else if (rsnd_is_gen4(priv)) {
+                       list    = gen4_id;
+                       nr      = ARRAY_SIZE(gen4_id);
                } else {
                        dev_err(dev, "unknown SSIU\n");
                        return -ENODEV;