diff options
Diffstat (limited to 'sound/soc/sh/rcar/gen.c')
| -rw-r--r-- | sound/soc/sh/rcar/gen.c | 207 |
1 files changed, 145 insertions, 62 deletions
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index add088bd4b2..1dd2b7d38c2 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -155,60 +155,99 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, return 0; } -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod; - int ret; - int id; +/* + * DMA read/write register offset + * + * RSND_xxx_I_N for Audio DMAC input + * RSND_xxx_O_N for Audio DMAC output + * RSND_xxx_I_P for Audio DMAC peri peri input + * RSND_xxx_O_P for Audio DMAC peri peri output + * + * ex) R-Car H2 case + * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out + * SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000 + * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 + * CMD : 0xec500000 / 0xec008000 0xec308000 + */ +#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) +#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) - /* - * Gen1 is created by SRU/SSI, and this SRU is base module of - * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU) - * - * Easy image is.. - * Gen1 SRU = Gen2 SCU + SSIU + etc - * - * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is - * using fixed path. - * - * Then, SSI id = SCU id here - */ +#define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) +#define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) - /* get SSI's ID */ - mod = rsnd_ssi_mod_get_frm_dai(priv, - rsnd_dai_id(priv, rdai), - rsnd_dai_is_play(rdai, io)); - id = rsnd_mod_id(mod); +#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) +#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - if (ret < 0) - return ret; - - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); +#define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i)) +#define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i)) - return ret; -} +#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) +#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +void rsnd_gen_dma_addr(struct rsnd_priv *priv, + struct rsnd_dma *dma, + struct dma_slave_config *cfg, + int is_play, int slave_id) { - struct rsnd_mod *mod, *n; - int ret = 0; + struct platform_device *pdev = rsnd_priv_to_pdev(priv); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + dma_addr_t ssi_reg = platform_get_resource(pdev, + IORESOURCE_MEM, RSND_GEN2_SSI)->start; + dma_addr_t src_reg = platform_get_resource(pdev, + IORESOURCE_MEM, RSND_GEN2_SCU)->start; + int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); + int use_src = !!rsnd_io_to_mod_src(io); + int use_dvc = !!rsnd_io_to_mod_dvc(io); + int id = rsnd_mod_id(mod); + struct dma_addr { + dma_addr_t src_addr; + dma_addr_t dst_addr; + } dma_addrs[2][2][3] = { + { /* SRC */ + /* Capture */ + {{ 0, 0 }, + { RDMA_SRC_O_N(src, id), 0 }, + { RDMA_CMD_O_N(src, id), 0 }}, + /* Playback */ + {{ 0, 0, }, + { 0, RDMA_SRC_I_N(src, id) }, + { 0, RDMA_SRC_I_N(src, id) }} + }, { /* SSI */ + /* Capture */ + {{ RDMA_SSI_O_N(ssi, id), 0 }, + { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }, + { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }}, + /* Playback */ + {{ 0, RDMA_SSI_I_N(ssi, id) }, + { RDMA_SRC_O_P(src, id), RDMA_SSI_I_P(ssi, id) }, + { RDMA_CMD_O_P(src, id), RDMA_SSI_I_P(ssi, id) }} + } + }; + + cfg->slave_id = slave_id; + cfg->src_addr = 0; + cfg->dst_addr = 0; + cfg->direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; /* - * remove all mod from rdai + * gen1 uses default DMA addr */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); + if (rsnd_is_gen1(priv)) + return; - return ret; + /* it shouldn't happen */ + if (use_dvc & !use_src) { + dev_err(dev, "DVC is selected without SRC\n"); + return; + } + + cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr; + cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr; + + dev_dbg(dev, "dma%d addr - src : %x / dst : %x\n", + id, cfg->src_addr, cfg->dst_addr); } /* @@ -229,14 +268,51 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), /* FIXME: it needs SSI_MODE2/3 in the future */ + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), + RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), + RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), + RSND_GEN2_M_REG(gen, SCU, CMD_ROUTE_SLCT, 0x18c, 0x20), + RSND_GEN2_M_REG(gen, SCU, CMD_CTRL, 0x190, 0x20), + RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), + RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), + RSND_GEN2_M_REG(gen, SCU, DVC_SWRSR, 0xe00, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_DVUIR, 0xe04, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_ADINR, 0xe08, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_DVUCR, 0xe10, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_ZCMCR, 0xe14, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_VOL0R, 0xe28, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_VOL1R, 0xe2c, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_DVUER, 0xe48, 0x100), + RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), + RSND_GEN2_S_REG(gen, ADG, DIV_EN, 0x30), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), + RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), + RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), + RSND_GEN2_S_REG(gen, ADG, CMDOUT_TIMSEL, 0x5c), RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), @@ -249,7 +325,6 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen2_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -283,13 +358,13 @@ static int rsnd_gen2_probe(struct platform_device *pdev, return ret; dev_dbg(dev, "Gen2 device probed\n"); - dev_dbg(dev, "SRU : %08x => %p\n", scu_res->start, + dev_dbg(dev, "SCU : %pap => %p\n", &scu_res->start, gen->base[RSND_GEN2_SCU]); - dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, + dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, gen->base[RSND_GEN2_ADG]); - dev_dbg(dev, "SSIU : %08x => %p\n", ssiu_res->start, + dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start, gen->base[RSND_GEN2_SSIU]); - dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start, + dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, gen->base[RSND_GEN2_SSI]); return 0; @@ -317,7 +392,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_CTRL, 0xc0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0), RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4), - RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4), + RSND_GEN1_M_REG(gen, SRU, SRC_BUSIF_MODE, 0x20, 0x4), RSND_GEN1_M_REG(gen, SRU, SRC_ROUTE_MODE0,0x50, 0x8), RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), @@ -347,7 +422,6 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) } static int rsnd_gen1_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -377,11 +451,11 @@ static int rsnd_gen1_probe(struct platform_device *pdev, return ret; dev_dbg(dev, "Gen1 device probed\n"); - dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start, + dev_dbg(dev, "SRU : %pap => %p\n", &sru_res->start, gen->base[RSND_GEN1_SRU]); - dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, + dev_dbg(dev, "ADG : %pap => %p\n", &adg_res->start, gen->base[RSND_GEN1_ADG]); - dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start, + dev_dbg(dev, "SSI : %pap => %p\n", &ssi_res->start, gen->base[RSND_GEN1_SSI]); return 0; @@ -391,14 +465,28 @@ static int rsnd_gen1_probe(struct platform_device *pdev, /* * Gen */ +static void rsnd_of_parse_gen(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = priv->info; + + if (!of_data) + return; + + info->flags = of_data->flags; +} + int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, + const struct rsnd_of_data *of_data, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_gen *gen; int ret; + rsnd_of_parse_gen(pdev, of_data, priv); + gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); if (!gen) { dev_err(dev, "GEN allocate failed\n"); @@ -409,17 +497,12 @@ int rsnd_gen_probe(struct platform_device *pdev, ret = -ENODEV; if (rsnd_is_gen1(priv)) - ret = rsnd_gen1_probe(pdev, info, priv); + ret = rsnd_gen1_probe(pdev, priv); else if (rsnd_is_gen2(priv)) - ret = rsnd_gen2_probe(pdev, info, priv); + ret = rsnd_gen2_probe(pdev, priv); if (ret < 0) dev_err(dev, "unknown generation R-Car sound device\n"); return ret; } - -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} |
