From 1b2ca0adf1a0cb3aa766259650eddd25b44486b7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 26 Oct 2015 08:43:21 +0000 Subject: [PATCH] ASoC: rsnd: use mod base common method on CMD Renesas sound needs many devices (SSI/SSIU/SRC/CTU/MIX/DVC/CMD/AudioDMAC/AudioDMACpp). SSI/SRC/CTU/MIX/DVC are implemented as module. SSI parent, SSIU are implemented as part of SSI CMD is implemented as part of CTU/MIX/DVC AudioDMAC/AudioDMACpp are implemented as part of SSI/SRC It is nice sense that these all devices are implemented as mod. This patch makes CMD mod base common method Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/Makefile | 2 +- sound/soc/sh/rcar/cmd.c | 153 +++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/core.c | 75 +----------------- sound/soc/sh/rcar/ctu.c | 8 ++ sound/soc/sh/rcar/dvc.c | 18 +++-- sound/soc/sh/rcar/mix.c | 10 ++- sound/soc/sh/rcar/rsnd.h | 20 ++++- 7 files changed, 202 insertions(+), 84 deletions(-) create mode 100644 sound/soc/sh/rcar/cmd.c diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 8b258501aa35..5f1000269cfb 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,4 +1,4 @@ -snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o +snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o cmd.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o snd-soc-rsrc-card-objs := rsrc-card.o diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c new file mode 100644 index 000000000000..731d74b13e92 --- /dev/null +++ b/sound/soc/sh/rcar/cmd.c @@ -0,0 +1,153 @@ +/* + * Renesas R-Car CMD support + * + * Copyright (C) 2015 Renesas Solutions Corp. + * Kuninori Morimoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "rsnd.h" + +struct rsnd_cmd { + struct rsnd_mod mod; +}; + +#define CMD_NAME "cmd" + +#define rsnd_cmd_nr(priv) ((priv)->cmd_nr) +#define for_each_rsnd_cmd(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_cmd_nr(priv)) && \ + ((pos) = (struct rsnd_cmd *)(priv)->cmd + i); \ + i++) + +static int rsnd_cmd_init(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) +{ + struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); + struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); + struct rsnd_mod *src = rsnd_io_to_mod_src(io); + struct device *dev = rsnd_priv_to_dev(priv); + u32 data; + + if (!mix && !dvc) + return 0; + + if (mix) { + struct rsnd_dai *rdai; + int i; + u32 path[] = { + [0] = 0, + [1] = 1 << 0, + [2] = 0, + [3] = 0, + [4] = 0, + [5] = 1 << 8 + }; + + /* + * it is assuming that integrater is well understanding about + * data path. Here doesn't check impossible connection, + * like src2 + src5 + */ + data = 0; + for_each_rsnd_dai(rdai, priv, i) { + io = &rdai->playback; + if (mix == rsnd_io_to_mod_mix(io)) + data |= path[rsnd_mod_id(src)]; + + io = &rdai->capture; + if (mix == rsnd_io_to_mod_mix(io)) + data |= path[rsnd_mod_id(src)]; + } + + } else { + u32 path[] = { + [0] = 0x30000, + [1] = 0x30001, + [2] = 0x40000, + [3] = 0x10000, + [4] = 0x20000, + [5] = 0x40100 + }; + + data = path[rsnd_mod_id(src)]; + } + + dev_dbg(dev, "ctu/mix path = 0x%08x", data); + + rsnd_mod_write(mod, CMD_ROUTE_SLCT, data); + + rsnd_mod_write(mod, CMD_CTRL, 0x10); + + return 0; +} + +static struct rsnd_mod_ops rsnd_cmd_ops = { + .name = CMD_NAME, + .init = rsnd_cmd_init, +}; + +int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id) +{ + struct rsnd_priv *priv = rsnd_io_to_priv(io); + struct rsnd_mod *mod = rsnd_cmd_mod_get(priv, id); + + return rsnd_dai_connect(mod, io, mod->type); +} + +struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id) +{ + if (WARN_ON(id < 0 || id >= rsnd_cmd_nr(priv))) + id = 0; + + return rsnd_mod_get((struct rsnd_cmd *)(priv->cmd) + id); +} + +int rsnd_cmd_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_cmd *cmd; + int i, nr, ret; + + /* This driver doesn't support Gen1 at this point */ + if (rsnd_is_gen1(priv)) + return 0; + + /* same number as DVC */ + nr = priv->dvc_nr; + if (!nr) + return 0; + + cmd = devm_kzalloc(dev, sizeof(*cmd) * nr, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + priv->cmd_nr = nr; + priv->cmd = cmd; + + for_each_rsnd_cmd(cmd, priv, i) { + ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), + &rsnd_cmd_ops, NULL, RSND_MOD_CMD, i); + if (ret) + return ret; + } + + return 0; +} + +void rsnd_cmd_remove(struct platform_device *pdev, + struct rsnd_priv *priv) +{ + struct rsnd_cmd *cmd; + int i; + + for_each_rsnd_cmd(cmd, priv, i) { + rsnd_mod_quit(rsnd_mod_get(cmd)); + } +} diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 8af2d22d0cd3..1cbd20f311b8 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -589,79 +589,6 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { ret; \ }) -void rsnd_path_parse(struct rsnd_priv *priv, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); - struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); - struct rsnd_mod *src = rsnd_io_to_mod_src(io); - struct rsnd_mod *cmd; - struct device *dev = rsnd_priv_to_dev(priv); - u32 data; - - /* Gen1 is not supported */ - if (rsnd_is_gen1(priv)) - return; - - if (!mix && !dvc) - return; - - if (mix) { - struct rsnd_dai *rdai; - int i; - u32 path[] = { - [0] = 0, - [1] = 1 << 0, - [2] = 0, - [3] = 0, - [4] = 0, - [5] = 1 << 8 - }; - - /* - * it is assuming that integrater is well understanding about - * data path. Here doesn't check impossible connection, - * like src2 + src5 - */ - data = 0; - for_each_rsnd_dai(rdai, priv, i) { - io = &rdai->playback; - if (mix == rsnd_io_to_mod_mix(io)) - data |= path[rsnd_mod_id(src)]; - - io = &rdai->capture; - if (mix == rsnd_io_to_mod_mix(io)) - data |= path[rsnd_mod_id(src)]; - } - - /* - * We can't use ctu = rsnd_io_ctu() here. - * Since, ID of dvc/mix are 0 or 1 (= same as CMD number) - * but ctu IDs are 0 - 7 (= CTU00 - CTU13) - */ - cmd = mix; - } else { - u32 path[] = { - [0] = 0x30000, - [1] = 0x30001, - [2] = 0x40000, - [3] = 0x10000, - [4] = 0x20000, - [5] = 0x40100 - }; - - data = path[rsnd_mod_id(src)]; - - cmd = dvc; - } - - dev_dbg(dev, "ctu/mix path = 0x%08x", data); - - rsnd_mod_write(cmd, CMD_ROUTE_SLCT, data); - - rsnd_mod_write(cmd, CMD_CTRL, 0x10); -} - static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -1208,6 +1135,7 @@ static int rsnd_probe(struct platform_device *pdev) rsnd_ctu_probe, rsnd_mix_probe, rsnd_dvc_probe, + rsnd_cmd_probe, rsnd_adg_probe, rsnd_dai_probe, }; @@ -1296,6 +1224,7 @@ static int rsnd_remove(struct platform_device *pdev) rsnd_ctu_remove, rsnd_mix_remove, rsnd_dvc_remove, + rsnd_cmd_remove, }; int ret = 0, i; diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 3cb214ab848b..6b76ae6cf549 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -31,6 +31,13 @@ static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) rsnd_mod_write(mod, CTU_CTUIR, enable); } +static int rsnd_ctu_probe_(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) +{ + return rsnd_cmd_attach(io, rsnd_mod_id(mod) / 4); +} + static int rsnd_ctu_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -57,6 +64,7 @@ static int rsnd_ctu_quit(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ctu_ops = { .name = CTU_NAME, + .probe = rsnd_ctu_probe_, .init = rsnd_ctu_init, .quit = rsnd_ctu_quit, }; diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 58f690900e6d..d207000efef0 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -134,9 +134,16 @@ static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, rsnd_mod_write(mod, DVC_DVUER, 1); } -static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) +static int rsnd_dvc_probe_(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) +{ + return rsnd_cmd_attach(io, rsnd_mod_id(mod)); +} + +static int rsnd_dvc_remove_(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) { struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); @@ -159,8 +166,6 @@ static int rsnd_dvc_init(struct rsnd_mod *mod, rsnd_dvc_initialize_lock(mod); - rsnd_path_parse(priv, io); - rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io)); /* ch0/ch1 Volume */ @@ -269,7 +274,8 @@ static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io, static struct rsnd_mod_ops rsnd_dvc_ops = { .name = DVC_NAME, .dma_req = rsnd_dvc_dma_req, - .remove = rsnd_dvc_remove_gen2, + .probe = rsnd_dvc_probe_, + .remove = rsnd_dvc_remove_, .init = rsnd_dvc_init, .quit = rsnd_dvc_quit, .start = rsnd_dvc_start, diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index 953dd0be9b60..bcbd821981a9 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -54,6 +54,13 @@ static void rsnd_mix_volume_update(struct rsnd_dai_stream *io, rsnd_mod_write(mod, MIX_MDBER, 1); } +static int rsnd_mix_probe_(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) +{ + return rsnd_cmd_attach(io, rsnd_mod_id(mod)); +} + static int rsnd_mix_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -66,8 +73,6 @@ static int rsnd_mix_init(struct rsnd_mod *mod, rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io)); - rsnd_path_parse(priv, io); - /* volume step */ rsnd_mod_write(mod, MIX_MIXMR, 0); rsnd_mod_write(mod, MIX_MVPDR, 0); @@ -90,6 +95,7 @@ static int rsnd_mix_quit(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_mix_ops = { .name = MIX_NAME, + .probe = rsnd_mix_probe_, .init = rsnd_mix_init, .quit = rsnd_mix_quit, }; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8d42642b1a45..5286f28de831 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -187,8 +187,6 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io); u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io); u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io); -void rsnd_path_parse(struct rsnd_priv *priv, - struct rsnd_dai_stream *io); /* * R-Car DMA @@ -210,6 +208,7 @@ enum rsnd_mod_type { RSND_MOD_DVC, RSND_MOD_MIX, RSND_MOD_CTU, + RSND_MOD_CMD, RSND_MOD_SRC, RSND_MOD_SSI, RSND_MOD_MAX, @@ -474,6 +473,12 @@ struct rsnd_priv { void *dvc; int dvc_nr; + /* + * below value will be filled on rsnd_cmd_probe() + */ + void *cmd; + int cmd_nr; + /* * below value will be filled on rsnd_dai_probe() */ @@ -606,6 +611,17 @@ void rsnd_dvc_remove(struct platform_device *pdev, struct rsnd_priv *priv); struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); +/* + * R-Car CMD + */ +int rsnd_cmd_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv); +void rsnd_cmd_remove(struct platform_device *pdev, + struct rsnd_priv *priv); +int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id); +struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id); + #ifdef DEBUG void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type); #define rsnd_mod_confirm_ssi(mssi) rsnd_mod_make_sure(mssi, RSND_MOD_SSI) -- 2.30.2