From 0290d2a42cb476358303d05fbe2475dd50889907 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:37:39 -0800 Subject: ASoC: rsnd: tidyup register naming of BUSIF_MODE Gen1:SRU has only 1 BUSIF_MODE, but Gen2:SSIU/SCU has SRCm_BUSIF_MODE, and SSIn_BUSIF_MODE. This patch rename current BUSIF_MODE to SRC_BUSIF_MODE. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 2 +- sound/soc/sh/rcar/rsnd.h | 2 +- sound/soc/sh/rcar/scu.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index add088bd4b2a..cbdbbfa322b8 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -317,7 +317,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), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4ca66cd899c8..f62b9eb274e1 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -39,8 +39,8 @@ enum rsnd_reg { RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, - RSND_REG_BUSIF_MODE, RSND_REG_INT_ENABLE, /* for Gen2 */ + RSND_REG_SRC_BUSIF_MODE, RSND_REG_SRC_ROUTE_MODE0, RSND_REG_SRC_SWRSR, RSND_REG_SRC_SRCIR, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 9bb08bb1d455..9b9daa3821a3 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -211,7 +211,7 @@ static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, rsnd_mod_write(mod, SRC_SRCIR, 0); /* use DMA transfer */ - rsnd_mod_write(mod, BUSIF_MODE, 1); + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); return 0; } -- cgit v1.2.3-55-g7522 From 92d9587ede108a7e73f80d0767aedf2c4edb47d8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:08 -0800 Subject: ASoC: rsnd: cleanup debug information method rsnd_mod debug information is implemented in each callback functions now. But, it can be implemented in rsnd_mod_call(), and share this code. This patch adds it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 11 ++++++++++- sound/soc/sh/rcar/scu.c | 2 -- sound/soc/sh/rcar/ssi.c | 12 ------------ 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index f62b9eb274e1..faacdcb8f05b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -152,10 +152,19 @@ struct rsnd_mod { #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) +#define __rsnd_mod_call(mod, func, rdai, io) \ +({ \ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ + struct device *dev = rsnd_priv_to_dev(priv); \ + dev_dbg(dev, "%s-%d-%s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + (mod)->ops->func(mod, rdai, io); \ +}) + #define rsnd_mod_call(mod, func, rdai, io) \ (!(mod) ? -ENODEV : \ !((mod)->ops->func) ? 0 : \ - (mod)->ops->func(mod, rdai, io)) + __rsnd_mod_call(mod, func, rdai, io)) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 9b9daa3821a3..e4b82ab31dca 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -300,8 +300,6 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - dev_dbg(dev, "%s%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 4b8cf7ca9d19..df775f0c8a2c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -324,7 +324,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -371,8 +370,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, rsnd_ssi_mode_set(priv, rdai, ssi); - dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } @@ -384,8 +381,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); - dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - if (ssi->err > 0) dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); @@ -450,7 +445,6 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct device *dev = rsnd_priv_to_dev(priv); /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; @@ -461,8 +455,6 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, rsnd_ssi_hw_start(ssi, rdai, io); - dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - return 0; } @@ -470,12 +462,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); - ssi->cr_etc = 0; rsnd_ssi_hw_stop(ssi, rdai); -- cgit v1.2.3-55-g7522 From 6acef1721c1046be8b5f44b839c28817cfbd66c6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:17 -0800 Subject: ASoC: rsnd: remove meaningless rsnd_ssi_non() rsnd_ssi_non_ops callback functions are never called. remove these meaningless callback Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index df775f0c8a2c..ef3d45045d1f 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -555,24 +555,8 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { /* * Non SSI */ -static int rsnd_ssi_non(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); - - dev_dbg(dev, "%s\n", __func__); - - return 0; -} - static struct rsnd_mod_ops rsnd_ssi_non_ops = { .name = "ssi (non)", - .init = rsnd_ssi_non, - .quit = rsnd_ssi_non, - .start = rsnd_ssi_non, - .stop = rsnd_ssi_non, }; /* -- cgit v1.2.3-55-g7522 From 013f38fe260af6f505ad5da5f6b0db3e42ca1fbb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:26 -0800 Subject: ASoC: rsnd: control SCU ops in probe timing SCU will be used if platform requested to use. Current driver is checking it in runtime, but, it can be decided in probe timing. This patch do it Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e4b82ab31dca..ab5f1d21731e 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -270,24 +270,10 @@ static int rsnd_scu_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct device *dev = rsnd_priv_to_dev(priv); int ret; - /* - * SCU will be used if it has RSND_SCU_USE_HPBIF flags - */ - if (!rsnd_scu_hpbif_is_enable(mod)) { - /* it use PIO transter */ - dev_dbg(dev, "%s%d is not used\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - - return 0; - } - clk_enable(scu->clk); - /* it use DMA transter */ - ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); if (ret < 0) return ret; @@ -310,9 +296,6 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - if (!rsnd_scu_hpbif_is_enable(mod)) - return 0; - rsnd_scu_transfer_stop(priv, mod, rdai, io); clk_disable(scu->clk); @@ -326,6 +309,10 @@ static struct rsnd_mod_ops rsnd_scu_ops = { .stop = rsnd_scu_stop, }; +static struct rsnd_mod_ops rsnd_scu_non_ops = { + .name = "scu (non)", +}; + struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) { if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) @@ -340,6 +327,7 @@ int rsnd_scu_probe(struct platform_device *pdev, { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_scu *scu; + struct rsnd_mod_ops *ops; struct clk *clk; char name[RSND_SCU_NAME_SIZE]; int i, nr; @@ -364,11 +352,15 @@ int rsnd_scu_probe(struct platform_device *pdev, if (IS_ERR(clk)) return PTR_ERR(clk); - rsnd_mod_init(priv, &scu->mod, - &rsnd_scu_ops, i); scu->info = &info->scu_info[i]; scu->clk = clk; + ops = &rsnd_scu_non_ops; + if (rsnd_scu_hpbif_is_enable(&scu->mod)) + ops = &rsnd_scu_ops; + + rsnd_mod_init(priv, &scu->mod, ops, i); + dev_dbg(dev, "SCU%d probed\n", i); } dev_dbg(dev, "scu probed\n"); -- cgit v1.2.3-55-g7522 From a204d90c91208d9b63ba309a1c44f582751e58c9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:33 -0800 Subject: ASoC: rsnd: add rsnd_scu_init(), and separate init/start Current scu.c has rsnd_scu_start(), and, operation of initialization/start are implemented in this function. This patch adds new rsnd_scu_init() and separates rsnd_scu_start(), since rsnd_mod_ops has .init/.start callbacks. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ab5f1d21731e..e1e08738b9d4 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -264,7 +264,7 @@ bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) return !!(flags & RSND_SCU_USE_HPBIF); } -static int rsnd_scu_start(struct rsnd_mod *mod, +static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { @@ -282,13 +282,30 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_transfer_start(priv, mod, rdai, io); - if (ret < 0) - return ret; + return 0; +} + +static int rsnd_scu_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + clk_disable(scu->clk); return 0; } +static int rsnd_scu_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + return rsnd_scu_transfer_start(priv, mod, rdai, io); +} + static int rsnd_scu_stop(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -298,13 +315,13 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, rsnd_scu_transfer_stop(priv, mod, rdai, io); - clk_disable(scu->clk); - return 0; } static struct rsnd_mod_ops rsnd_scu_ops = { .name = "scu", + .init = rsnd_scu_init, + .quit = rsnd_scu_quit, .start = rsnd_scu_start, .stop = rsnd_scu_stop, }; -- cgit v1.2.3-55-g7522 From 47718dc7d8ca5f5509ac9beb13486642306bb36b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:42 -0800 Subject: ASoC: rsnd: remove meaningless function parameter struct rsnd_priv *priv on rsnd_scu_init/start/stop() are no longer needed Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e1e08738b9d4..ece539b758d1 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -50,7 +50,7 @@ struct rsnd_scu { i++) /* Gen1 only */ -static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, +static int rsnd_src_set_route_if_gen1( struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -69,6 +69,7 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 mask; u32 val; @@ -149,11 +150,12 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, return rate; } -static int rsnd_scu_convert_rate_ctrl(struct rsnd_priv *priv, +static int rsnd_scu_convert_rate_ctrl( struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 convert_rate = rsnd_scu_convert_rate(scu); @@ -268,17 +270,16 @@ static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int ret; clk_enable(scu->clk); - ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); + ret = rsnd_src_set_route_if_gen1(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io); + ret = rsnd_scu_convert_rate_ctrl(mod, rdai, io); if (ret < 0) return ret; -- cgit v1.2.3-55-g7522 From e7ce74eaa76591e5a4905d0fc07a278533447b80 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:38:50 -0800 Subject: ASoC: rsnd: merge rsnd_scu_start/stop() and rsnd_scu_transfer_start/stop() rsnd_scu_transfer_start/stop() are no longer needed. merge into rsnd_scu_start/stop() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 56 +++++++++++++------------------------------------ 1 file changed, 14 insertions(+), 42 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ece539b758d1..5d2dbbbf9d98 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -218,46 +218,6 @@ static int rsnd_scu_convert_rate_ctrl( return 0; } -static int rsnd_scu_transfer_start(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 val; - - if (rsnd_is_gen1(priv)) { - val = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); - - return 0; -} - -static int rsnd_scu_transfer_stop(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); - u32 mask; - - if (rsnd_is_gen1(priv)) { - mask = (1 << id); - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, mask, 0); - } - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); - - return 0; -} - bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) { struct rsnd_scu *scu = rsnd_mod_to_scu(mod); @@ -303,8 +263,15 @@ static int rsnd_scu_start(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); - return rsnd_scu_transfer_start(priv, mod, rdai, io); + if (rsnd_is_gen1(priv)) + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; } static int rsnd_scu_stop(struct rsnd_mod *mod, @@ -313,8 +280,13 @@ static int rsnd_scu_stop(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); + + if (rsnd_is_gen1(priv)) + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - rsnd_scu_transfer_stop(priv, mod, rdai, io); + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); return 0; } -- cgit v1.2.3-55-g7522 From e779a20da90b12d17af74fe544fafd814b66dc63 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:12 -0800 Subject: ASoC: rsnd: rsnd_dai_is_clk_master() can be shared Current rsnd driver is using ssi local rsnd_rdai_is_clk_master() for checking clock master. But it can be rsnd_dai_is_clk_master(), and share in each file Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/ssi.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index faacdcb8f05b..cd396dda85c5 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -215,6 +215,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); +#define rsnd_dai_is_clk_master(rdai) ((rdai)->clk_master) /* * R-Car Gen1/Gen2 diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index ef3d45045d1f..ddcca067908c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -95,7 +95,6 @@ struct rsnd_ssiu { #define rsnd_ssi_dma_available(ssi) \ rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) -#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) #define rsnd_ssi_to_ssiu(ssi)\ @@ -133,7 +132,7 @@ static void rsnd_ssi_mode_set(struct rsnd_priv *priv, #define ssi_parent_set(p, sync, adg, ext) \ do { \ ssi->parent = ssiu->ssi + p; \ - if (rsnd_rdai_is_clk_master(rdai)) \ + if (rsnd_dai_is_clk_master(rdai)) \ val = adg; \ else \ val = ext; \ @@ -252,7 +251,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, if (0 == ssi->usrcnt) { clk_enable(ssi->clk); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, rdai, io); else @@ -302,7 +301,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, rsnd_mod_write(&ssi->mod, SSICR, cr); /* disabled all */ rsnd_ssi_status_check(&ssi->mod, IIRQ); - if (rsnd_rdai_is_clk_master(rdai)) { + if (rsnd_dai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_stop(ssi->parent, rdai); else @@ -522,7 +521,7 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, rsnd_ssi_hw_start(ssi, ssi->rdai, io); /* enable WS continue */ - if (rsnd_rdai_is_clk_master(rdai)) + if (rsnd_dai_is_clk_master(rdai)) rsnd_mod_write(&ssi->mod, SSIWSR, CONT); return 0; -- cgit v1.2.3-55-g7522 From 6f3ab6c1c022e7a4877d38940cd45ae7804a15e2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:23 -0800 Subject: ASoC: rsnd: remove pin sync option Renesas Chip is supporting multi pin sound, but the HW setting is very difficult and confusable. But driver is supporting it halfway. Remove SYNC option at this point. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 1 + sound/soc/sh/rcar/ssi.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 6add6ccc811e..1d19bfc2486d 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -35,6 +35,7 @@ */ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) #define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */ +#define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */ #define RSND_SSI_PLAY (1 << 24) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index ddcca067908c..68393a9f91bf 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -136,8 +136,6 @@ static void rsnd_ssi_mode_set(struct rsnd_priv *priv, val = adg; \ else \ val = ext; \ - if (flags & RSND_SSI_SYNC) \ - val |= sync; \ } while (0) flags = rsnd_ssi_mode_flags(ssi); -- cgit v1.2.3-55-g7522 From 7b5ce9759a60ebdffa1e76224ccb3d85bd06e4ac Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:32 -0800 Subject: ASoC: rsnd: SSI_MODE0/1 settings goes to scu.c SRU (Gen1) / SCU (Gen2) / SSIU (Gen2) are controlled under scu.c. (SCU + SSIU (Gen2) was SRU (Gen1)) And register of SSI_MODE0/1 are mapped on these IP. But these have been implemented under ssi.c on this driver. The naming is very confusable, but it should be implemented under scu.c Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/scu.c | 45 ++++++++++++++++++++++ sound/soc/sh/rcar/ssi.c | 98 ++++++++++++++---------------------------------- 3 files changed, 74 insertions(+), 70 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index cd396dda85c5..85b926229b81 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -321,5 +321,6 @@ void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); #endif diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 5d2dbbbf9d98..ade10474a0cf 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -49,6 +49,46 @@ struct rsnd_scu { ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ i++) +static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + int id = rsnd_mod_id(mod); + + /* + * SSI_MODE0 + */ + rsnd_mod_bset(mod, SSI_MODE0, (1 << id), + rsnd_scu_hpbif_is_enable(mod) ? 0 : (1 << id)); + + /* + * SSI_MODE1 + */ + if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + int shift = -1; + switch (id) { + case 1: + shift = 0; + break; + case 2: + shift = 2; + break; + case 4: + shift = 16; + break; + } + + if (shift >= 0) + rsnd_mod_bset(mod, SSI_MODE1, + 0x3 << shift, + rsnd_dai_is_clk_master(rdai) ? + 0x2 << shift : 0x1 << shift); + } + + return 0; +} + /* Gen1 only */ static int rsnd_src_set_route_if_gen1( struct rsnd_mod *mod, @@ -235,6 +275,10 @@ static int rsnd_scu_init(struct rsnd_mod *mod, clk_enable(scu->clk); + ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + if (ret < 0) + return ret; + ret = rsnd_src_set_route_if_gen1(mod, rdai, io); if (ret < 0) return ret; @@ -301,6 +345,7 @@ static struct rsnd_mod_ops rsnd_scu_ops = { static struct rsnd_mod_ops rsnd_scu_non_ops = { .name = "scu (non)", + .init = rsnd_scu_ssi_mode_init, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 68393a9f91bf..0f314db8cb50 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -75,9 +75,6 @@ struct rsnd_ssi { }; struct rsnd_ssiu { - u32 ssi_mode0; - u32 ssi_mode1; - int ssi_nr; struct rsnd_ssi *ssi; }; @@ -100,70 +97,6 @@ struct rsnd_ssiu { #define rsnd_ssi_to_ssiu(ssi)\ (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) -static void rsnd_ssi_mode_set(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_ssi *ssi) -{ - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_mod *scu; - struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi); - int id = rsnd_mod_id(&ssi->mod); - u32 flags; - u32 val; - - scu = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod)); - - /* - * SSI_MODE0 - */ - - /* see also BUSIF_MODE */ - if (rsnd_scu_hpbif_is_enable(scu)) { - ssiu->ssi_mode0 &= ~(1 << id); - dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id); - } else { - ssiu->ssi_mode0 |= (1 << id); - dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id); - } - - /* - * SSI_MODE1 - */ -#define ssi_parent_set(p, sync, adg, ext) \ - do { \ - ssi->parent = ssiu->ssi + p; \ - if (rsnd_dai_is_clk_master(rdai)) \ - val = adg; \ - else \ - val = ext; \ - } while (0) - - flags = rsnd_ssi_mode_flags(ssi); - if (flags & RSND_SSI_CLK_PIN_SHARE) { - - val = 0; - switch (id) { - case 1: - ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0)); - break; - case 2: - ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2)); - break; - case 4: - ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16)); - break; - case 8: - ssi_parent_set(7, 0, 0, 0); - break; - } - - ssiu->ssi_mode1 |= val; - } - - rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0); - rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1); -} - static void rsnd_ssi_status_check(struct rsnd_mod *mod, u32 bit) { @@ -320,7 +253,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -365,8 +297,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ - rsnd_ssi_mode_set(priv, rdai, ssi); - return 0; } @@ -588,6 +518,32 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; } +int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); +} + +static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) +{ + if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) + return; + + switch (rsnd_mod_id(&ssi->mod)) { + case 1: + case 2: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0)); + break; + case 4: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 3)); + break; + case 8: + ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 7)); + break; + } +} + int rsnd_ssi_probe(struct platform_device *pdev, struct rcar_snd_info *info, struct rsnd_priv *priv) @@ -668,6 +624,8 @@ int rsnd_ssi_probe(struct platform_device *pdev, } rsnd_mod_init(priv, &ssi->mod, ops, i); + + rsnd_ssi_parent_clk_setup(priv, ssi); } dev_dbg(dev, "ssi probed\n"); -- cgit v1.2.3-55-g7522 From dd27d808f9e084e7e9c4719c17f17d1fa35c45a6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:40 -0800 Subject: ASoC: rsnd: remove ssiu from ssi.c Now, SSI_MODE0/1 are controlled under scu.c ssiu is no longer needed on ssi.c Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 3 ++- sound/soc/sh/rcar/ssi.c | 24 +++++++----------------- 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 85b926229b81..e92b1f438f74 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -280,7 +280,8 @@ struct rsnd_priv { /* * below value will be filled on rsnd_ssi_probe() */ - void *ssiu; + void *ssi; + int ssi_nr; /* * below value will be filled on rsnd_dai_probe() diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0f314db8cb50..dc72439da58d 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -74,18 +74,13 @@ struct rsnd_ssi { unsigned int rate; }; -struct rsnd_ssiu { - int ssi_nr; - struct rsnd_ssi *ssi; -}; - #define for_each_rsnd_ssi(pos, priv, i) \ for (i = 0; \ (i < rsnd_ssi_nr(priv)) && \ - ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \ + ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \ i++) -#define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr) +#define rsnd_ssi_nr(priv) ((priv)->ssi_nr) #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0) @@ -94,8 +89,6 @@ struct rsnd_ssiu { #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) -#define rsnd_ssi_to_ssiu(ssi)\ - (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1) static void rsnd_ssi_status_check(struct rsnd_mod *mod, u32 bit) @@ -515,7 +508,7 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id) if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv))) id = 0; - return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod; + return &((struct rsnd_ssi *)(priv->ssi) + id)->mod; } int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) @@ -552,7 +545,6 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; struct clk *clk; - struct rsnd_ssiu *ssiu; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; int i, nr, ret; @@ -561,16 +553,14 @@ int rsnd_ssi_probe(struct platform_device *pdev, * init SSI */ nr = info->ssi_info_nr; - ssiu = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr), - GFP_KERNEL); - if (!ssiu) { + ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL); + if (!ssi) { dev_err(dev, "SSI allocate failed\n"); return -ENOMEM; } - priv->ssiu = ssiu; - ssiu->ssi = (struct rsnd_ssi *)(ssiu + 1); - ssiu->ssi_nr = nr; + priv->ssi = ssi; + priv->ssi_nr = nr; for_each_rsnd_ssi(ssi, priv, i) { pinfo = &info->ssi_info[i]; -- cgit v1.2.3-55-g7522 From f80e1c96339a45992b5dded0474288e52bd3b18d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:48 -0800 Subject: ASoC: rsnd: rename rsnd_scu_convert_rate_ctrl() rsnd_scu_convert_rate_ctrl() is unclear naming, and there is "rsnd_scu_convert_rate" variable. These are confusable. it renamed to rsnd_scu_set_convert_rate() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index ade10474a0cf..872a115cd224 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -190,10 +190,9 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, return rate; } -static int rsnd_scu_convert_rate_ctrl( - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); @@ -283,7 +282,7 @@ static int rsnd_scu_init(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_convert_rate_ctrl(mod, rdai, io); + ret = rsnd_scu_set_convert_rate(mod, rdai, io); if (ret < 0) return ret; -- cgit v1.2.3-55-g7522 From 41c6221c39accdc4fe2b0c0fa196b6302b704e57 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:39:56 -0800 Subject: ASoC: rsnd: explain SRC bypass mode settings in comment SRC bypass mode is useful for debugging. This patch explains SRC bypass mode settings in comment Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 872a115cd224..076aa71bc102 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -40,6 +40,51 @@ struct rsnd_scu { * */ +/* + * How to use SRC bypass mode for debugging + * + * SRC has bypass mode, and it is useful for debugging. + * In Gen2 case, + * SRCm_MODE controls whether SRC is used or not + * SSI_MODE0 controls whether SSIU which receives SRC data + * is used or not. + * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, + * but SRC bypass mode needs SSI_MODE0 only. + * + * This driver request + * struct rsnd_scu_platform_info { + * u32 flags; + * u32 convert_rate; + * } + * + * rsnd_scu_hpbif_is_enable() will be true + * if flags had RSND_SCU_USE_HPBIF, + * and it controls whether SSIU is used or not. + * + * rsnd_scu_convert_rate() indicates + * above convert_rate, and it controls + * whether SRC is used or not. + * + * ex) doesn't use SRC + * struct rsnd_scu_platform_info info = { + * .flags = 0, + * .convert_rate = 0, + * }; + * + * ex) uses SRC + * struct rsnd_scu_platform_info info = { + * .flags = RSND_SCU_USE_HPBIF, + * .convert_rate = 48000, + * }; + * + * ex) uses SRC bypass mode + * struct rsnd_scu_platform_info info = { + * .flags = RSND_SCU_USE_HPBIF, + * .convert_rate = 0, + * }; + * + */ + #define rsnd_mod_to_scu(_mod) \ container_of((_mod), struct rsnd_scu, mod) -- cgit v1.2.3-55-g7522 From 9b5ab573a81b9ac0df90b74d732651fdf8b24525 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:03 -0800 Subject: ASoC: rsnd: remove duplicate *priv from rsnd_dma *priv pointer exists under rsnd_mod, and, it can get rsnd_mod pointer from rsnd_dma. remove duplicate rsnd_dma :: priv Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 5 ++--- sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 743de5e3b1e1..ed8611f9c64f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -156,7 +156,7 @@ void rsnd_dma_stop(struct rsnd_dma *dma) static void rsnd_dma_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; - struct rsnd_priv *priv = dma->priv; + struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); unsigned long flags; rsnd_lock(priv, flags); @@ -172,7 +172,7 @@ static void rsnd_dma_complete(void *data) static void rsnd_dma_do_work(struct work_struct *work) { struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); - struct rsnd_priv *priv = dma->priv; + struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; dma_addr_t buf; @@ -246,7 +246,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma->priv = priv; dma->inquiry = inquiry; dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e92b1f438f74..33c01fb9f5fd 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -96,7 +96,6 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, * R-Car DMA */ struct rsnd_dma { - struct rsnd_priv *priv; struct sh_dmae_slave slave; struct work_struct work; struct dma_chan *chan; -- cgit v1.2.3-55-g7522 From 106d2eff563b2abdb34872cb8ec7b19766edaffc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:13 -0800 Subject: ASoC: rsnd: non 0 is error on probe Some xxx_probe() returns not only -Exx, but also PTR_ERR(). Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed8611f9c64f..4fd57351c54a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -737,23 +737,23 @@ static int rsnd_probe(struct platform_device *pdev) * init each module */ ret = rsnd_gen_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_scu_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_adg_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_ssi_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; ret = rsnd_dai_probe(pdev, info, priv); - if (ret < 0) + if (ret) return ret; /* -- cgit v1.2.3-55-g7522 From 64de62b38641dec05905930024133726c540040e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:20 -0800 Subject: ASoC: rsnd: fixup Gen2 module naming Gen2 has SCU, not SRU Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index cbdbbfa322b8..76828c20fb50 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -283,7 +283,7 @@ 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 : %08x => %p\n", scu_res->start, gen->base[RSND_GEN2_SCU]); dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, gen->base[RSND_GEN2_ADG]); -- cgit v1.2.3-55-g7522 From f5cab3b8976d59c6166228874a5af3d87c94c723 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:27 -0800 Subject: ASoC: rsnd: don't use schedule_work() when rsnd_dma_start() rsnd_dma_start() is the function to start DMAEngine. Current code is using schedule_work() for it, but it breaks DMAC/SSI register setting timing. Don't use schedule_work() on it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 4fd57351c54a..11eb0e35b9ce 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -132,6 +132,7 @@ void rsnd_mod_init(struct rsnd_priv *priv, /* * rsnd_dma functions */ +static void __rsnd_dma_start(struct rsnd_dma *dma); static void rsnd_dma_continue(struct rsnd_dma *dma) { /* push next A or B plane */ @@ -143,7 +144,7 @@ void rsnd_dma_start(struct rsnd_dma *dma) { /* push both A and B plane*/ dma->submit_loop = 2; - schedule_work(&dma->work); + __rsnd_dma_start(dma); } void rsnd_dma_stop(struct rsnd_dma *dma) @@ -169,9 +170,8 @@ static void rsnd_dma_complete(void *data) rsnd_unlock(priv, flags); } -static void rsnd_dma_do_work(struct work_struct *work) +static void __rsnd_dma_start(struct rsnd_dma *dma) { - struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; @@ -204,6 +204,13 @@ static void rsnd_dma_do_work(struct work_struct *work) } } +static void rsnd_dma_do_work(struct work_struct *work) +{ + struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); + + __rsnd_dma_start(dma); +} + int rsnd_dma_available(struct rsnd_dma *dma) { return !!dma->chan; -- cgit v1.2.3-55-g7522 From be213ac1af893410eb8256010edf136b4099e827 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:34 -0800 Subject: ASoC: rsnd: SCU should be called before SSI Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 76828c20fb50..db486aae6b8b 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -182,14 +182,14 @@ int rsnd_gen_path_init(struct rsnd_priv *priv, rsnd_dai_is_play(rdai, io)); id = rsnd_mod_id(mod); - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); + /* SCU */ + mod = rsnd_scu_mod_get(priv, id); ret = rsnd_dai_connect(rdai, mod, io); if (ret < 0) return ret; - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); + /* SSI */ + mod = rsnd_ssi_mod_get(priv, id); ret = rsnd_dai_connect(rdai, mod, io); return ret; -- cgit v1.2.3-55-g7522 From c926b746055adfd915936c67244e635e9c7a3d84 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:41 -0800 Subject: ASoC: rsnd: clarify scu.c area scu.c cares SRU(Gen1) / SCU(Gen2) / SSIU(Gen2) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 076aa71bc102..1adc85825f4e 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -40,6 +40,20 @@ struct rsnd_scu { * */ +/* + * scu.c is caring... + * + * Gen1 + * + * [mem] -> [SRU] -> [SSI] + * |--------| + * + * Gen2 + * + * [mem] -> [SCU] -> [SSIU] -> [SSI] + * |-----------------| + */ + /* * How to use SRC bypass mode for debugging * -- cgit v1.2.3-55-g7522 From 39cf3c4064b8db25efe501fec8e3c48a578b4b58 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:47 -0800 Subject: ASoC: rsnd: Merge macros in scu.c Merge #define lines, since these are defined in the scattering place Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 1adc85825f4e..8181ec55ad21 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -16,9 +16,6 @@ struct rsnd_scu { struct clk *clk; }; -#define rsnd_scu_mode_flags(p) ((p)->info->flags) -#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) - #define RSND_SCU_NAME_SIZE 16 /* @@ -30,6 +27,18 @@ struct rsnd_scu { #define OTBL_18 (6 << 16) #define OTBL_16 (8 << 16) +#define rsnd_scu_mode_flags(p) ((p)->info->flags) +#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_mod_to_scu(_mod) \ + container_of((_mod), struct rsnd_scu, mod) + +#define for_each_rsnd_scu(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_scu_nr(priv)) && \ + ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ + i++) + + /* * image of SRC (Sampling Rate Converter) * @@ -99,15 +108,6 @@ struct rsnd_scu { * */ -#define rsnd_mod_to_scu(_mod) \ - container_of((_mod), struct rsnd_scu, mod) - -#define for_each_rsnd_scu(pos, priv, i) \ - for ((i) = 0; \ - ((i) < rsnd_scu_nr(priv)) && \ - ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ - i++) - static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) -- cgit v1.2.3-55-g7522 From 96c7c0d6f8c6e09e9123f0518130c047c5de40f6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:40:54 -0800 Subject: ASoC: rsnd: rsnd_scu_hpbif_is_enable() become macro rsnd_scu_hpbif_is_enable() is used only scu.c now. It can be local macro Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 - sound/soc/sh/rcar/scu.c | 15 +++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 33c01fb9f5fd..a9c58305e2f1 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -303,7 +303,6 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_mod *ssi_mod, struct snd_pcm_runtime *runtime); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 8181ec55ad21..2f839f72c99c 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -31,6 +31,8 @@ struct rsnd_scu { #define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) #define rsnd_mod_to_scu(_mod) \ container_of((_mod), struct rsnd_scu, mod) +#define rsnd_scu_hpbif_is_enable(scu) \ + (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) #define for_each_rsnd_scu(pos, priv, i) \ for ((i) = 0; \ @@ -113,13 +115,14 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); /* * SSI_MODE0 */ rsnd_mod_bset(mod, SSI_MODE0, (1 << id), - rsnd_scu_hpbif_is_enable(mod) ? 0 : (1 << id)); + rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << id)); /* * SSI_MODE1 @@ -316,14 +319,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, return 0; } -bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 flags = rsnd_scu_mode_flags(scu); - - return !!(flags & RSND_SCU_USE_HPBIF); -} - static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -449,7 +444,7 @@ int rsnd_scu_probe(struct platform_device *pdev, scu->clk = clk; ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(&scu->mod)) + if (rsnd_scu_hpbif_is_enable(scu)) ops = &rsnd_scu_ops; rsnd_mod_init(priv, &scu->mod, ops, i); -- cgit v1.2.3-55-g7522 From 28dc4b63cdb96f2448a677320fcc0eb112e13e3f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:10 -0800 Subject: ASoC: rsnd: merge SRC clock timing/setting SRC clock and timing setting register exist in SRU and ADG on Gen1. But, these are merged into ADG on Gen2. Current driver is supporting Gen1 SRC only at this point, but, above settings are set as different function. This patch merges these as preparation of Gen2 support. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 20 ++++---------------- sound/soc/sh/rcar/rsnd.h | 8 ++++---- sound/soc/sh/rcar/scu.c | 48 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 43 insertions(+), 33 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a53235c4d1b0..5bdffa480245 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,10 +30,10 @@ struct rsnd_adg { i++, (pos) = adg->clk[i]) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); @@ -91,18 +91,6 @@ find_rate: return 0; } -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate) -{ - if (rsnd_is_gen1(priv)) - return rsnd_adg_set_convert_clk_gen1(priv, mod, - src_rate, dst_rate); - - return -EINVAL; -} - static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) { int id = rsnd_mod_id(mod); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a9c58305e2f1..39914558e857 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -246,10 +246,10 @@ int rsnd_adg_probe(struct platform_device *pdev, struct rsnd_priv *priv); void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv); -int rsnd_adg_set_convert_clk(struct rsnd_priv *priv, - struct rsnd_mod *mod, - unsigned int src_rate, - unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, + struct rsnd_mod *mod, + unsigned int src_rate, + unsigned int dst_rate); /* * R-Car sound priv diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 2f839f72c99c..e2ffcc415057 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -172,10 +172,8 @@ static int rsnd_src_set_route_if_gen1( { 0x3, 30, }, /* 8 */ }; struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 mask; u32 val; - int shift; int id; /* @@ -197,6 +195,23 @@ static int rsnd_src_set_route_if_gen1( rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); + return 0; +} + +static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate = rsnd_scu_convert_rate(scu); + u32 mask; + u32 val; + int shift; + int id = rsnd_mod_id(mod); + int ret; + /* * SRC_TIMING_SELECT */ @@ -209,12 +224,23 @@ static int rsnd_src_set_route_if_gen1( * SSI WS is used as source clock if SRC is not used * (when playback, source/destination become reverse when capture) */ - if (rsnd_scu_convert_rate(scu)) /* use ADG */ + ret = 0; + if (convert_rate) { + /* use ADG */ val = 0; - else if (8 == id) /* use SSI WS, but SRU8 is special */ + ret = rsnd_adg_set_convert_clk_gen1(priv, mod, + runtime->rate, + convert_rate); + } else if (8 == id) { + /* use SSI WS, but SRU8 is special */ val = id << shift; - else /* use SSI WS */ + } else { + /* use SSI WS */ val = (id + 1) << shift; + } + + if (ret < 0) + return ret; switch (id / 4) { case 0: @@ -284,7 +310,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, if (convert_rate) { u32 fsrate = 0x0400000 / convert_rate * runtime->rate; - int ret; /* Enable the initial value of IFS */ rsnd_mod_write(mod, SRC_IFSCR, 1); @@ -301,13 +326,6 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, if (rsnd_is_gen1(priv)) { /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ } - - /* set convert clock */ - ret = rsnd_adg_set_convert_clk(priv, mod, - runtime->rate, - convert_rate); - if (ret < 0) - return ret; } /* Cancel the initialization and operate the SRC function */ @@ -340,6 +358,10 @@ static int rsnd_scu_init(struct rsnd_mod *mod, if (ret < 0) return ret; + ret = rsnd_scu_set_convert_timing_gen1(mod, rdai, io); + if (ret < 0) + return ret; + return 0; } -- cgit v1.2.3-55-g7522 From 32f27ebf9b625df610c12408ea15bae37be75eaf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:17 -0800 Subject: ASoC: rsnd: add rsnd_ssi_is_play() SCU needs SSI direction if Gen2. Add rsnd_ssi_is_play() function for it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/ssi.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 39914558e857..b1874eb71436 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -321,5 +321,6 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); +int rsnd_ssi_is_play(struct rsnd_mod *mod); #endif diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index dc72439da58d..bae309c9f0fb 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -494,7 +494,7 @@ struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, if (rsnd_ssi_dai_id(ssi) != dai_id) continue; - has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); + has_play = rsnd_ssi_is_play(&ssi->mod); if (is_play == has_play) return &ssi->mod; @@ -518,6 +518,13 @@ int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); } +int rsnd_ssi_is_play(struct rsnd_mod *mod) +{ + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + + return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY); +} + static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi) { if (!rsnd_ssi_is_pin_sharing(&ssi->mod)) @@ -582,7 +589,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, if (pinfo->dma_id > 0) { ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), - (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY), + rsnd_ssi_is_play(&ssi->mod), pinfo->dma_id, rsnd_ssi_dma_inquiry, rsnd_ssi_dma_complete); -- cgit v1.2.3-55-g7522 From 1b7b08efbe7419cc3e082f2b5ec8ae89f7af43d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:36 -0800 Subject: ASoC: rsnd: extracts Gen1/Gen2 common parts Renesas sound IP Gen1/Gen2 are similar, but different. This patch extracts Gen1/Gen2 common and dependency parts, and create Gen1/Gen2 ops to control it. According to this structure, SSIU setup which has been implemented on ssi.c can be moved to scu.c (SRU/SSIU/SCU should be implemented on scu.c) Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 2 +- sound/soc/sh/rcar/scu.c | 336 ++++++++++++++++++++++++++++------------------- sound/soc/sh/rcar/ssi.c | 5 - 3 files changed, 205 insertions(+), 138 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b1874eb71436..c397dc8edee5 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -48,7 +48,7 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, - RSND_REG_SRC_MNFSR, + RSND_REG_SRC_MNFSR, /* for Gen1 */ /* ADG */ RSND_REG_BRRA, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index e2ffcc415057..29d8990e3f0f 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -110,6 +110,9 @@ struct rsnd_scu { * */ +/* + * Gen1/Gen2 common functions + */ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -151,11 +154,145 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, return 0; } -/* Gen1 only */ -static int rsnd_src_set_route_if_gen1( - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_mod *ssi_mod, + struct snd_pcm_runtime *runtime) +{ + struct rsnd_scu *scu; + unsigned int rate; + + /* this function is assuming SSI id = SCU id here */ + scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_scu_convert_rate(scu); + if (!rate) + rate = runtime->rate; + + return rate; +} + +static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + u32 adinr = runtime->channels; + u32 fsrate = 0; + + if (convert_rate) + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* set/clear soft reset */ + rsnd_mod_write(mod, SRC_SWRSR, 0); + rsnd_mod_write(mod, SRC_SWRSR, 1); + + /* + * Initialize the operation of the SRC internal circuits + * see rsnd_scu_start() + */ + rsnd_mod_write(mod, SRC_SRCIR, 1); + + /* Set channel number and output bit length */ + switch (runtime->sample_bits) { + case 16: + adinr |= OTBL_16; + break; + case 32: + adinr |= OTBL_24; + break; + default: + return -EIO; + } + rsnd_mod_write(mod, SRC_ADINR, adinr); + + /* Enable the initial value of IFS */ + if (fsrate) { + rsnd_mod_write(mod, SRC_IFSCR, 1); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + } + + /* use DMA transfer */ + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + + return 0; +} + +static int rsnd_scu_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int ret; + + clk_enable(scu->clk); + + ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_scu_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + clk_disable(scu->clk); + + return 0; +} + +static int rsnd_scu_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + /* + * Cancel the initialization and operate the SRC function + * see rsnd_scu_set_convert_rate() + */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; +} + + +static int rsnd_scu_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + if (rsnd_scu_convert_rate(scu)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); + + return 0; +} + +static struct rsnd_mod_ops rsnd_scu_non_ops = { + .name = "scu (non)", +}; + +/* + * Gen1 functions + */ +static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { struct scu_route_config { u32 mask; @@ -171,17 +308,10 @@ static int rsnd_src_set_route_if_gen1( { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); u32 mask; u32 val; int id; - /* - * Gen1 only - */ - if (!rsnd_is_gen1(priv)) - return 0; - id = rsnd_mod_id(mod); if (id < 0 || id >= ARRAY_SIZE(routes)) return -EIO; @@ -257,104 +387,43 @@ static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, return 0; } -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, - struct snd_pcm_runtime *runtime) -{ - struct rsnd_scu *scu; - unsigned int rate; - - /* this function is assuming SSI id = SCU id here */ - scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); - - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_scu_convert_rate(scu); - if (!rate) - rate = runtime->rate; - - return rate; -} - -static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 adinr = runtime->channels; - - /* set/clear soft reset */ - rsnd_mod_write(mod, SRC_SWRSR, 0); - rsnd_mod_write(mod, SRC_SWRSR, 1); - - /* Initialize the operation of the SRC internal circuits */ - rsnd_mod_write(mod, SRC_SRCIR, 1); - - /* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); - - if (convert_rate) { - u32 fsrate = 0x0400000 / convert_rate * runtime->rate; - - /* Enable the initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSCR, 1); - - /* Set initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSVR, fsrate); - - /* Select SRC mode (fixed value) */ - rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); + int ret; - /* Set the restriction value of the FS ratio (98%) */ - rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98); + ret = rsnd_scu_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; - if (rsnd_is_gen1(priv)) { - /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ - } - } + /* Select SRC mode (fixed value) */ + rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); - /* Cancel the initialization and operate the SRC function */ - rsnd_mod_write(mod, SRC_SRCIR, 0); + /* Set the restriction value of the FS ratio (98%) */ + rsnd_mod_write(mod, SRC_MNFSR, + rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); - /* use DMA transfer */ - rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ return 0; } -static int rsnd_scu_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int ret; - clk_enable(scu->clk); - - ret = rsnd_scu_ssi_mode_init(mod, rdai, io); + ret = rsnd_scu_init(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_src_set_route_if_gen1(mod, rdai, io); + ret = rsnd_src_set_route_gen1(mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_scu_set_convert_rate(mod, rdai, io); + ret = rsnd_scu_set_convert_rate_gen1(mod, rdai, io); if (ret < 0) return ret; @@ -365,62 +434,58 @@ static int rsnd_scu_init(struct rsnd_mod *mod, return 0; } -static int rsnd_scu_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + int id = rsnd_mod_id(mod); - clk_disable(scu->clk); + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - return 0; + return rsnd_scu_start(mod, rdai, io); } -static int rsnd_scu_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +static int rsnd_scu_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); - if (rsnd_is_gen1(priv)) - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - return 0; + return rsnd_scu_stop(mod, rdai, io); } -static int rsnd_scu_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); +static struct rsnd_mod_ops rsnd_scu_gen1_ops = { + .name = "sru (gen1)", + .init = rsnd_scu_init_gen1, + .quit = rsnd_scu_quit, + .start = rsnd_scu_start_gen1, + .stop = rsnd_scu_stop_gen1, +}; - if (rsnd_is_gen1(priv)) - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); +static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { + .name = "non-sru (gen1)", + .init = rsnd_scu_ssi_mode_init, +}; - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); +/* + * Gen2 functions + */ +static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + /* enable PIO interrupt */ + rsnd_mod_write(mod, INT_ENABLE, 0x0f000000); return 0; } -static struct rsnd_mod_ops rsnd_scu_ops = { - .name = "scu", - .init = rsnd_scu_init, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start, - .stop = rsnd_scu_stop, -}; - -static struct rsnd_mod_ops rsnd_scu_non_ops = { - .name = "scu (non)", +static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { + .name = "non-scu (gen2)", .init = rsnd_scu_ssi_mode_init, + .start = rsnd_scu_start_non_gen2, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) @@ -466,8 +531,15 @@ int rsnd_scu_probe(struct platform_device *pdev, scu->clk = clk; ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(scu)) - ops = &rsnd_scu_ops; + if (rsnd_scu_hpbif_is_enable(scu)) { + if (rsnd_is_gen1(priv)) + ops = &rsnd_scu_gen1_ops; + } else { + if (rsnd_is_gen1(priv)) + ops = &rsnd_scu_non_gen1_ops; + if (rsnd_is_gen2(priv)) + ops = &rsnd_scu_non_gen2_ops; + } rsnd_mod_init(priv, &scu->mod, ops, i); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index bae309c9f0fb..b7f464ebcdc0 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -363,16 +363,11 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - /* enable PIO interrupt if gen2 */ - if (rsnd_is_gen2(priv)) - rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); - rsnd_ssi_hw_start(ssi, rdai, io); return 0; -- cgit v1.2.3-55-g7522 From 4686a0ad9aaee89495f181e5755d153e7fe7ffe6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:44 -0800 Subject: ASoC: rsnd: remove SSI dependent DMAEngine callback Renesas Gen2 sound will use 2 DMAC which are Audio-DMAC, and Audio-DMAC-peri-peri. Current driver has callback function for each DMAC, because it assumed each DMAC needs special settings. But it became clear that these can share settings. This patch removes unnecessary callback Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 38 +++++++++++++++++++++++++++----------- sound/soc/sh/rcar/rsnd.h | 10 +++++----- sound/soc/sh/rcar/ssi.c | 47 ++++++++--------------------------------------- 3 files changed, 40 insertions(+), 55 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 11eb0e35b9ce..b5af6f5145ea 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -143,6 +143,7 @@ static void rsnd_dma_continue(struct rsnd_dma *dma) void rsnd_dma_start(struct rsnd_dma *dma) { /* push both A and B plane*/ + dma->offset = 0; dma->submit_loop = 2; __rsnd_dma_start(dma); } @@ -157,12 +158,26 @@ void rsnd_dma_stop(struct rsnd_dma *dma) static void rsnd_dma_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); unsigned long flags; rsnd_lock(priv, flags); - dma->complete(dma); + /* + * Renesas sound Gen1 needs 1 DMAC, + * Gen2 needs 2 DMAC. + * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri. + * But, Audio-DMAC-peri-peri doesn't have interrupt, + * and this driver is assuming that here. + * + * If Audio-DMAC-peri-peri has interrpt, + * rsnd_dai_pointer_update() will be called twice, + * ant it will breaks io->byte_pos + */ + + rsnd_dai_pointer_update(io, io->byte_per_period); if (dma->submit_loop) rsnd_dma_continue(dma); @@ -172,17 +187,21 @@ static void rsnd_dma_complete(void *data) static void __rsnd_dma_start(struct rsnd_dma *dma) { - struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; dma_addr_t buf; - size_t len; + size_t len = io->byte_per_period; int i; for (i = 0; i < dma->submit_loop; i++) { - if (dma->inquiry(dma, &buf, &len) < 0) - return; + buf = runtime->dma_addr + + rsnd_dai_pointer_offset(io, dma->offset + len); + dma->offset = len; desc = dmaengine_prep_slave_single( dma->chan, buf, len, dma->dir, @@ -217,10 +236,7 @@ int rsnd_dma_available(struct rsnd_dma *dma) } int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, - dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)) + int is_play, int id) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; @@ -253,8 +269,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, goto rsnd_dma_init_err; dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - dma->inquiry = inquiry; - dma->complete = complete; INIT_WORK(&dma->work, rsnd_dma_do_work); return 0; @@ -307,6 +321,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, } list_add_tail(&mod->list, &io->head); + mod->io = io; return 0; } @@ -314,6 +329,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, int rsnd_dai_disconnect(struct rsnd_mod *mod) { list_del_init(&mod->list); + mod->io = NULL; return 0; } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c397dc8edee5..b2c717d2ba7e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -100,19 +100,16 @@ struct rsnd_dma { struct work_struct work; struct dma_chan *chan; enum dma_data_direction dir; - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len); - int (*complete)(struct rsnd_dma *dma); int submit_loop; + int offset; /* it cares A/B plane */ }; void rsnd_dma_start(struct rsnd_dma *dma); void rsnd_dma_stop(struct rsnd_dma *dma); int rsnd_dma_available(struct rsnd_dma *dma); int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id, - int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len), - int (*complete)(struct rsnd_dma *dma)); + int is_play, int id); void rsnd_dma_quit(struct rsnd_priv *priv, struct rsnd_dma *dma); @@ -137,17 +134,20 @@ struct rsnd_mod_ops { struct rsnd_dai_stream *io); }; +struct rsnd_dai_stream; struct rsnd_mod { int id; struct rsnd_priv *priv; struct rsnd_mod_ops *ops; struct list_head list; /* connect to rsnd_dai playback/capture */ struct rsnd_dma dma; + struct rsnd_dai_stream *io; }; #define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_dma(mod) (&(mod)->dma) #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) +#define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index b7f464ebcdc0..d3371d798d54 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -64,12 +64,10 @@ struct rsnd_ssi { struct rsnd_mod mod; struct rsnd_dai *rdai; - struct rsnd_dai_stream *io; u32 cr_own; u32 cr_clk; u32 cr_etc; int err; - int dma_offset; unsigned int usrcnt; unsigned int rate; }; @@ -286,7 +284,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, * set ssi parameter */ ssi->rdai = rdai; - ssi->io = io; ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ @@ -305,7 +302,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err); ssi->rdai = NULL; - ssi->io = NULL; ssi->cr_own = 0; ssi->err = 0; @@ -329,8 +325,9 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) { struct rsnd_ssi *ssi = data; - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); + struct rsnd_mod *mod = &ssi->mod; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + u32 status = rsnd_mod_read(mod, SSISR); irqreturn_t ret = IRQ_NONE; if (io && (status & DIRQ)) { @@ -347,9 +344,9 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) * see rsnd_ssi_init() */ if (rsnd_dai_is_play(rdai, io)) - rsnd_mod_write(&ssi->mod, SSITDR, *buf); + rsnd_mod_write(mod, SSITDR, *buf); else - *buf = rsnd_mod_read(&ssi->mod, SSIRDR); + *buf = rsnd_mod_read(mod, SSIRDR); rsnd_dai_pointer_update(io, sizeof(*buf)); @@ -394,33 +391,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .stop = rsnd_ssi_pio_stop, }; -static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len) -{ - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - - *len = io->byte_per_period; - *buf = runtime->dma_addr + - rsnd_dai_pointer_offset(io, ssi->dma_offset + *len); - ssi->dma_offset = *len; /* it cares A/B plane */ - - return 0; -} - -static int rsnd_ssi_dma_complete(struct rsnd_dma *dma) -{ - struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma); - struct rsnd_dai_stream *io = ssi->io; - u32 status = rsnd_mod_read(&ssi->mod, SSISR); - - rsnd_ssi_record_error(ssi, status); - - rsnd_dai_pointer_update(ssi->io, io->byte_per_period); - - return 0; -} - static int rsnd_ssi_dma_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -430,7 +400,6 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, /* enable DMA transfer */ ssi->cr_etc = DMEN; - ssi->dma_offset = 0; rsnd_dma_start(dma); @@ -452,6 +421,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, ssi->cr_etc = 0; + rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR)); + rsnd_ssi_hw_stop(ssi, rdai); rsnd_dma_stop(dma); @@ -585,9 +556,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), rsnd_ssi_is_play(&ssi->mod), - pinfo->dma_id, - rsnd_ssi_dma_inquiry, - rsnd_ssi_dma_complete); + pinfo->dma_id); if (ret < 0) dev_info(dev, "SSI DMA failed. try PIO transter\n"); else -- cgit v1.2.3-55-g7522 From eb854f6dff24a59378acc8d8eda57a3543a25acc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:41:51 -0800 Subject: ASoC: rsnd: rsnd_ssi_probe() goes forwarder than rsnd_scu_probe() rsnd_ssi_probe() goes forwarder than rsnd_scu_probe(), since scu will need ssi information on Gen2 Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index b5af6f5145ea..f316a663e4d3 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -763,15 +763,15 @@ static int rsnd_probe(struct platform_device *pdev) if (ret) return ret; - ret = rsnd_scu_probe(pdev, info, priv); + ret = rsnd_ssi_probe(pdev, info, priv); if (ret) return ret; - ret = rsnd_adg_probe(pdev, info, priv); + ret = rsnd_scu_probe(pdev, info, priv); if (ret) return ret; - ret = rsnd_ssi_probe(pdev, info, priv); + ret = rsnd_adg_probe(pdev, info, priv); if (ret) return ret; -- cgit v1.2.3-55-g7522 From 629509c5bc478c0343d94c8c70812396f44447fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 23 Jan 2014 18:42:00 -0800 Subject: ASoC: rsnd: add Gen2 SRC and DMAEngine support Renesas sound Gen2 has SRC (= Sampling Rate Converter) which needs 2 DMAC. The data path image when you use SRC on Gen2 is [mem] -> Audio-DMAC -> SRC -> Audio-DMAC-peri-peri -> SSIU -> SSI This patch support SRC and DMAEnine. It is tested on R-Car H2 Lager board Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 6 +++ sound/soc/sh/rcar/adg.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/gen.c | 26 +++++++++ sound/soc/sh/rcar/rsnd.h | 25 +++++++++ sound/soc/sh/rcar/scu.c | 117 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 312 insertions(+) (limited to 'sound') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 1d19bfc2486d..2be05aea54f9 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -56,9 +56,15 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ +#define RSND_SCU_SET(rate, _dma_id) \ + { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } +#define RSND_SCU_UNUSED \ + { .flags = 0, .convert_rate = 0, .dma_id = 0, } + struct rsnd_scu_platform_info { u32 flags; u32 convert_rate; /* sampling rate convert */ + int dma_id; /* for Gen2 SCU */ }; /* diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 5bdffa480245..821791e15d04 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,6 +30,144 @@ struct rsnd_adg { i++, (pos) = adg->clk[i]) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) + +static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + int id = rsnd_mod_id(mod); + int ws = id; + + if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + switch (id) { + case 1: + case 2: + ws = 0; + break; + case 4: + ws = 3; + break; + case 8: + ws = 7; + break; + } + } + + return (0x6 + ws) << 8; +} + +static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + u32 timsel) +{ + int is_play = rsnd_dai_is_play(rdai, io); + int id = rsnd_mod_id(mod); + int shift = (id % 2) ? 16 : 0; + u32 mask, ws; + u32 in, out; + + ws = rsnd_adg_ssi_ws_timing_gen2(mod); + + in = (is_play) ? timsel : ws; + out = (is_play) ? ws : timsel; + + in = in << shift; + out = out << shift; + mask = 0xffff << shift; + + switch (id / 2) { + case 0: + rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out); + break; + case 1: + rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out); + break; + case 2: + rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out); + break; + case 3: + rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out); + break; + case 4: + rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in); + rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out); + break; + } + + return 0; +} + +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int idx, sel, div, step; + u32 val; + unsigned int min, diff; + unsigned int sel_rate [] = { + clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ + clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ + clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ + adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ + adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ + }; + + min = ~0; + val = 0; + for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { + idx = 0; + step = 2; + + if (!sel_rate[sel]) + continue; + + for (div = 2; div <= 98304; div += step) { + diff = abs(src_rate - sel_rate[sel] / div); + if (min > diff) { + val = (sel << 8) | idx; + min = diff; + } + + /* + * step of 0_0000 / 0_0001 / 0_1101 + * are out of order + */ + if ((idx > 2) && (idx % 2)) + step *= 2; + if (idx == 0x1c) { + div += step; + step *= 2; + } + idx++; + } + } + + if (min == ~0) { + dev_err(dev, "no Input clock\n"); + return -EIO; + } + + return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); +} + +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + u32 val = rsnd_adg_ssi_ws_timing_gen2(mod); + + return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); +} + int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index db486aae6b8b..3e03a8bc4f75 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -229,14 +229,40 @@ 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_S_REG(gen, SSIU, SSI_CONTROL, 0x810), + 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, 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_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, 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_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b2c717d2ba7e..8b66dc15fa73 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -37,6 +37,11 @@ enum rsnd_reg { RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ + RSND_REG_SRC_CTRL, /* for Gen2 */ + RSND_REG_SSI_CTRL, /* for Gen2 */ + RSND_REG_SSI_CONTROL, + RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ + RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, RSND_REG_INT_ENABLE, /* for Gen2 */ @@ -49,6 +54,8 @@ enum rsnd_reg { RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, RSND_REG_SRC_MNFSR, /* for Gen1 */ + RSND_REG_SRC_BSDSR, /* for Gen2 */ + RSND_REG_SRC_BSISR, /* for Gen2 */ /* ADG */ RSND_REG_BRRA, @@ -60,6 +67,16 @@ enum rsnd_reg { RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ + RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ + RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ + RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ /* SSI */ RSND_REG_SSICR, @@ -250,6 +267,14 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, unsigned int dst_rate); +int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io, + unsigned int src_rate, + unsigned int dst_rate); +int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); /* * R-Car sound priv diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 29d8990e3f0f..6e5c763e1040 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -33,6 +33,8 @@ struct rsnd_scu { container_of((_mod), struct rsnd_scu, mod) #define rsnd_scu_hpbif_is_enable(scu) \ (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) +#define rsnd_scu_dma_available(scu) \ + rsnd_dma_available(rsnd_mod_to_dma(&(scu)->mod)) #define for_each_rsnd_scu(pos, priv, i) \ for ((i) = 0; \ @@ -472,6 +474,103 @@ static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { /* * Gen2 functions */ +static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_scu_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + + rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); + + rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); + rsnd_mod_write(mod, SRC_BSISR, 0x00100060); + + return 0; +} + +static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + int ret; + + if (convert_rate) + ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, + runtime->rate, + convert_rate); + else + ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); + + return ret; +} + +static int rsnd_scu_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_scu_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_scu_set_convert_rate_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_scu_set_convert_timing_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_scu_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + rsnd_dma_start(rsnd_mod_to_dma(&scu->mod)); + + rsnd_mod_write(mod, SSI_CTRL, 0x1); + rsnd_mod_write(mod, SRC_CTRL, 0x11); + + return rsnd_scu_start(mod, rdai, io); +} + +static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + + rsnd_mod_write(mod, SSI_CTRL, 0); + rsnd_mod_write(mod, SRC_CTRL, 0); + + rsnd_dma_stop(rsnd_mod_to_dma(&scu->mod)); + + return rsnd_scu_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_scu_gen2_ops = { + .name = "scu (gen2)", + .init = rsnd_scu_init_gen2, + .quit = rsnd_scu_quit, + .start = rsnd_scu_start_gen2, + .stop = rsnd_scu_stop_gen2, +}; + static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -534,6 +633,17 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_scu_hpbif_is_enable(scu)) { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; + if (rsnd_is_gen2(priv)) { + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); + int ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(&scu->mod), + rsnd_ssi_is_play(ssi), + scu->info->dma_id); + if (ret < 0) + return ret; + + ops = &rsnd_scu_gen2_ops; + } } else { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_non_gen1_ops; @@ -553,4 +663,11 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv) { + struct rsnd_scu *scu; + int i; + + for_each_rsnd_scu(scu, priv, i) { + if (rsnd_scu_dma_available(scu)) + rsnd_dma_quit(priv, rsnd_mod_to_dma(&scu->mod)); + } } -- cgit v1.2.3-55-g7522 From 8691d0748e566f8708f7a9139e760134f5dc3130 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 7 Feb 2014 00:53:06 -0800 Subject: ASoC: rsnd: use device dependency clock Current R-Car sound driver is using device independent audio clock, but it is not good design for DT support. This patch adds device dependent clock support. But, there are some platform which is using independent audio clock. It is still supported at this point, but it will be removed soon. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 821791e15d04..8d3a82ef2db5 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -385,8 +385,9 @@ int rsnd_adg_probe(struct platform_device *pdev, { struct rsnd_adg *adg; struct device *dev = rsnd_priv_to_dev(priv); - struct clk *clk; + struct clk *clk, *clk_orig; int i; + bool use_old_style = false; adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); if (!adg) { @@ -394,10 +395,39 @@ int rsnd_adg_probe(struct platform_device *pdev, return -ENOMEM; } - adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); - adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); - adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); - adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + clk_orig = clk_get(dev, NULL); + adg->clk[CLKA] = clk_get(dev, "clk_a"); + adg->clk[CLKB] = clk_get(dev, "clk_b"); + adg->clk[CLKC] = clk_get(dev, "clk_c"); + adg->clk[CLKI] = clk_get(dev, "clk_i"); + + /* + * It request device dependent audio clock. + * But above all clks will indicate rsnd module clock + * if platform doesn't it + */ + for_each_rsnd_clk(clk, adg, i) { + if (clk_orig == clk) { + dev_warn(dev, + "doesn't have device dependent clock, use independent clock\n"); + use_old_style = true; + break; + } + } + + /* + * note: + * these exist in order to keep compatible with + * platform which has device independent audio clock, + * but will be removed soon + */ + if (use_old_style) { + adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); + adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); + adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); + adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + } + for_each_rsnd_clk(clk, adg, i) { if (IS_ERR(clk)) { dev_err(dev, "Audio clock failed\n"); -- cgit v1.2.3-55-g7522 From 9a6d48605e632e84db2895cf752c65b3c908cd09 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Sat, 8 Feb 2014 15:59:52 +0800 Subject: ASoC: add snd_soc_of_parse_audio_simple_widgets for DT This patch adds snd_soc_of_parse_audio_simple_widgets() and supports below style of widgets name on DT: "template-wname", "user supplied wname" For instance: simple-audio-widgets = "Microphone", "Microphone Jack", "Line", "Line In Jack", "Line", "Line Out Jack", "Headphone", "Headphone Jack", "Speaker", "Speaker External"; The "template-wname" currently includes: "Microphone", "Line", "Headphone" and "Speaker". Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- include/sound/soc.h | 2 ++ sound/soc/soc-core.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) (limited to 'sound') diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..465dc6e0674d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1173,6 +1173,8 @@ void snd_soc_util_exit(void); int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..0540cb08e0ea 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -4417,6 +4417,93 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name); +static const struct snd_soc_dapm_widget simple_widgets[] = { + SND_SOC_DAPM_MIC("Microphone", NULL), + SND_SOC_DAPM_LINE("Line", NULL), + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, + const char *propname) +{ + struct device_node *np = card->dev->of_node; + struct snd_soc_dapm_widget *widgets; + const char *template, *wname; + int i, j, num_widgets, ret; + + num_widgets = of_property_count_strings(np, propname); + if (num_widgets < 0) { + dev_err(card->dev, + "ASoC: Property '%s' does not exist\n", propname); + return -EINVAL; + } + if (num_widgets & 1) { + dev_err(card->dev, + "ASoC: Property '%s' length is not even\n", propname); + return -EINVAL; + } + + num_widgets /= 2; + if (!num_widgets) { + dev_err(card->dev, "ASoC: Property '%s's length is zero\n", + propname); + return -EINVAL; + } + + widgets = devm_kcalloc(card->dev, num_widgets, sizeof(*widgets), + GFP_KERNEL); + if (!widgets) { + dev_err(card->dev, + "ASoC: Could not allocate memory for widgets\n"); + return -ENOMEM; + } + + for (i = 0; i < num_widgets; i++) { + ret = of_property_read_string_index(np, propname, + 2 * i, &template); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, 2 * i, ret); + return -EINVAL; + } + + for (j = 0; j < ARRAY_SIZE(simple_widgets); j++) { + if (!strncmp(template, simple_widgets[j].name, + strlen(simple_widgets[j].name))) { + widgets[i] = simple_widgets[j]; + break; + } + } + + if (j >= ARRAY_SIZE(simple_widgets)) { + dev_err(card->dev, + "ASoC: DAPM widget '%s' is not supported\n", + template); + return -EINVAL; + } + + ret = of_property_read_string_index(np, propname, + (2 * i) + 1, + &wname); + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' index %d read error:%d\n", + propname, (2 * i) + 1, ret); + return -EINVAL; + } + + widgets[i].name = wname; + } + + card->dapm_widgets = widgets; + card->num_dapm_widgets = num_widgets; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) { -- cgit v1.2.3-55-g7522 From 00463c113b6ba6506b4f1ebb9b3c5dd249f8750f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 17:15:51 -0800 Subject: ASoC: rsnd: tidyup original for_each_rsnd_xxx macro Current for_each_rsnd_xxx macro will read out-of-array's memory after last loop operation. It was not good C language operation, and the binary which was compiled by (at least) gcc 4.8.1 is broken This patch tidyup these issues Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 7 ++++--- sound/soc/sh/rcar/rsnd.h | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 8d3a82ef2db5..bc8961c5e986 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -25,9 +25,10 @@ struct rsnd_adg { }; #define for_each_rsnd_clk(pos, adg, i) \ - for (i = 0, (pos) = adg->clk[i]; \ - i < CLKMAX; \ - i++, (pos) = adg->clk[i]) + for (i = 0; \ + (i < CLKMAX) && \ + ((pos) = adg->clk[i]); \ + i++) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8b66dc15fa73..9e4efb40416b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -216,9 +216,10 @@ struct rsnd_dai { #define rsnd_dai_nr(priv) ((priv)->dai_nr) #define for_each_rsnd_dai(rdai, priv, i) \ - for (i = 0, (rdai) = rsnd_dai_get(priv, i); \ - i < rsnd_dai_nr(priv); \ - i++, (rdai) = rsnd_dai_get(priv, i)) + for (i = 0; \ + (i < rsnd_dai_nr(priv)) && \ + ((rdai) = rsnd_dai_get(priv, i)); \ + i++) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); int rsnd_dai_disconnect(struct rsnd_mod *mod); -- cgit v1.2.3-55-g7522 From ee2c828d21b2381c813df257235d3c635269e435 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 21:04:12 -0800 Subject: ASoC: rsnd: set DIV_EN register on rsnd_adg_set_convert_clk_gen2() DIV_EN register enable bit is required when you use Gen2 SRC Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 16 +++++++++++++--- sound/soc/sh/rcar/gen.c | 1 + sound/soc/sh/rcar/rsnd.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index bc8961c5e986..af9e4407aa89 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -111,8 +111,8 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); - int idx, sel, div, step; - u32 val; + int idx, sel, div, step, ret; + u32 val, en; unsigned int min, diff; unsigned int sel_rate [] = { clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ @@ -124,6 +124,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, min = ~0; val = 0; + en = 0; for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { idx = 0; step = 2; @@ -136,6 +137,7 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, if (min > diff) { val = (sel << 8) | idx; min = diff; + en = 1 << (sel + 1); /* fixme */ } /* @@ -157,7 +159,15 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, return -EIO; } - return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); + ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); + if (ret < 0) { + dev_err(dev, "timsel error\n"); + return ret; + } + + rsnd_mod_bset(mod, DIV_EN, en, en); + + return 0; } int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 3e03a8bc4f75..0a43b906ffdf 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -253,6 +253,7 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) 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), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9e4efb40416b..d4093907dfd8 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -67,6 +67,7 @@ enum rsnd_reg { RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ + RSND_REG_DIV_EN, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ -- cgit v1.2.3-55-g7522 From a2070feede404484296aace813b6c518582a3f8e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 11 Feb 2014 21:05:26 -0800 Subject: ASoC: rsnd: print error if there is SRC settings mismatch rsnd request clock master if SRC is used Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 6e5c763e1040..3984d4b4f2df 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -122,6 +122,14 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); int id = rsnd_mod_id(mod); + u32 convert_rate = rsnd_scu_convert_rate(scu); + + if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { + struct device *dev = rsnd_priv_to_dev(priv); + + dev_err(dev, "rsnd should be clk master when you rate convert\n"); + return -EINVAL; + } /* * SSI_MODE0 -- cgit v1.2.3-55-g7522 From 9b87a5b0d4aad02e9dff299b63cd85930eb233d8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 22 Feb 2014 18:44:17 +0100 Subject: ASoC: pxa: Remove superfluous locking The locking here was added in commit 71a295602e ("ASoC: Lock the CODEC in PXA external jack controls") to protect the DAPM changes that are made inside of ${board}_ext_control() against concurrent updates. The ASoC core was updated in commit a73fb2df01 ("ASoC: dapm: Use DAPM mutex for DAPM ops instead of codec mutex") to use a card wide lock rather the CODEC mutex to protect DAPM operations. We now have proper locking inside ${board}_ext_control() itself, so taking the CODEC lock can be removed. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 4 ---- sound/soc/pxa/magician.c | 4 ---- sound/soc/pxa/poodle.c | 4 ---- sound/soc/pxa/spitz.c | 4 ---- sound/soc/pxa/tosa.c | 4 ---- 5 files changed, 20 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 1853d41034bf..b51f88002e62 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -99,13 +99,9 @@ static int corgi_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ corgi_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index aace19e0fe2c..aeb08f5f3e1c 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -73,13 +73,9 @@ static int magician_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ magician_ext_control(codec); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index c93e138d8dc3..27c6c03bc5d7 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -76,13 +76,9 @@ static int poodle_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ poodle_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index fc052d8247ff..0728c1eb780c 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -108,13 +108,9 @@ static int spitz_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ spitz_ext_control(&codec->dapm); - mutex_unlock(&codec->mutex); - return 0; } diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 1d9c2ed223bc..d6f38d7ecc1c 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -80,13 +80,9 @@ static int tosa_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; - mutex_lock(&codec->mutex); - /* check the jack status at stream startup */ tosa_ext_control(codec); - mutex_unlock(&codec->mutex); - return 0; } -- cgit v1.2.3-55-g7522 From 7cb5e1bb9f91bf984f26b520072a22610235d869 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:47:34 +0100 Subject: ASoC: omap: Use SOC_ENUM_SINGLE_EXT_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/omap/ams-delta.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index 629446482a91..99b314d53790 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -194,13 +194,11 @@ static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, return 0; } -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; +static const SOC_ENUM_SINGLE_EXT_DECL(ams_delta_audio_enum, + ams_delta_audio_mode); static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], + SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum, ams_delta_get_audio_mode, ams_delta_set_audio_mode), }; -- cgit v1.2.3-55-g7522 From c3518d1bd45ebfdfd88480e5781054fed378fb22 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:36 +0100 Subject: ASoC: ml26124: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ml26124.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index 185fa3bc3052..577fb8776ce7 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -73,11 +73,11 @@ static const DECLARE_TLV_DB_SCALE(ngth, -7650, 150, 0); static const char * const ml26124_companding[] = {"16bit PCM", "u-law", "A-law"}; -static const struct soc_enum ml26124_adc_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_TRANS_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum, + ML26124_SAI_TRANS_CTL, 6, ml26124_companding); -static const struct soc_enum ml26124_dac_companding_enum - = SOC_ENUM_SINGLE(ML26124_SAI_RCV_CTL, 6, 3, ml26124_companding); +static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum, + ML26124_SAI_RCV_CTL, 6, ml26124_companding); static const struct snd_kcontrol_new ml26124_snd_controls[] = { SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0, @@ -136,8 +136,8 @@ static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = { static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in", "Digital MIC in", "Analog MIC Differential in"}; -static const struct soc_enum ml26124_insel_enum = - SOC_ENUM_SINGLE(ML26124_MIC_IF_CTL, 0, 3, ml26124_input_select); +static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum, + ML26124_MIC_IF_CTL, 0, ml26124_input_select); static const struct snd_kcontrol_new ml26124_input_mux_controls = SOC_DAPM_ENUM("Input Select", ml26124_insel_enum); -- cgit v1.2.3-55-g7522 From 89c6785715592a6b082b3f9f28c27bb14b041c7d Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 14 Feb 2014 09:34:35 +0800 Subject: ASoC: core: add TDM slot parsing from DT supports For some CPU/CODEC DAI devices the TDM slot infomation maybe needed. This patch adds the slot parsing from DT supports. TDM slot properties: dai-tdm-slot-num : Number of slots in use. dai-tdm-slot-width : Width in bits for each slot. For instance: dai-tdm-slot-num = <2>; dai-tdm-slot-width = <8>; And for each spcified driver, there could be one .of_xlate_tdm_slot_mask() to specify a explicit mapping of the channels and the slots. If it's absent the default snd_soc_of_xlate_tdm_slot_mask() will be used to generating the tx and rx masks. For snd_soc_of_xlate_tdm_slot_mask(), the tx and rx masks will use a 1 bit for an active slot as default, and the default active bits are at the LSB of the masks. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 ++ include/sound/soc.h | 3 +++ sound/soc/soc-core.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) (limited to 'sound') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 71f27c403194..d86e0fc41e80 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -142,6 +142,8 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); + int (*of_xlate_tdm_slot_mask)(unsigned int slots, + unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); diff --git a/include/sound/soc.h b/include/sound/soc.h index 465dc6e0674d..2a878d03c147 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1175,6 +1175,9 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width); int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0540cb08e0ea..5b7d3ba87c7a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3608,6 +3608,30 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) } EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); +/** + * snd_soc_of_xlate_tdm_slot - generate tx/rx slot mask. + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * Generates the TDM tx and rx slot default masks for DAI. + */ +static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (*tx_mask || *rx_mask) + return 0; + + if (!slots) + return -EINVAL; + + *tx_mask = (1 << slots) - 1; + *rx_mask = (1 << slots) - 1; + + return 0; +} + /** * snd_soc_dai_set_tdm_slot - configure DAI TDM. * @dai: DAI @@ -3622,6 +3646,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { + if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) + dai->driver->ops->of_xlate_tdm_slot_mask(slots, + &tx_mask, &rx_mask); + else + snd_soc_of_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + if (dai->driver && dai->driver->ops->set_tdm_slot) return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); @@ -4504,6 +4534,35 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets); +int snd_soc_of_parse_tdm_slot(struct device_node *np, + unsigned int *slots, + unsigned int *slot_width) +{ + u32 val; + int ret; + + if (of_property_read_bool(np, "dai-tdm-slot-num")) { + ret = of_property_read_u32(np, "dai-tdm-slot-num", &val); + if (ret) + return ret; + + if (slots) + *slots = val; + } + + if (of_property_read_bool(np, "dai-tdm-slot-width")) { + ret = of_property_read_u32(np, "dai-tdm-slot-width", &val); + if (ret) + return ret; + + if (slot_width) + *slot_width = val; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot); + int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname) { -- cgit v1.2.3-55-g7522 From 498480731e232d7c9a96a338924b5a275121e091 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:14:33 -0800 Subject: ASoC: rsnd: move priv member settings to upper side There is no big meaning, but preparation for platform dai support Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f316a663e4d3..a8e6aa6cb334 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -594,6 +594,10 @@ static int rsnd_dai_probe(struct platform_device *pdev, return -ENOMEM; } + priv->dai_nr = dai_nr; + priv->daidrv = drv; + priv->rdai = rdai; + for (i = 0; i < dai_nr; i++) { pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); @@ -630,10 +634,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, cmod ? "capture" : " -- "); } - priv->dai_nr = dai_nr; - priv->daidrv = drv; - priv->rdai = rdai; - return 0; } -- cgit v1.2.3-55-g7522 From d870a91e9d0eae524ac2da7cbdc7e399a71b86c4 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:14:41 -0800 Subject: ASoC: rsnd: move rsnd_mod_call() macro core.c is the only user of rsnd_mod_call() macro. Move it to core.c from rsnd.h Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 34 ++++++++++++++++++++++++---------- sound/soc/sh/rcar/rsnd.h | 13 ------------- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index a8e6aa6cb334..5f6d9fef23d1 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -291,16 +291,30 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * rsnd_dai functions */ -#define rsnd_dai_call(rdai, io, fn) \ -({ \ - struct rsnd_mod *mod, *n; \ - int ret = 0; \ - for_each_rsnd_mod(mod, n, io) { \ - ret = rsnd_mod_call(mod, fn, rdai, io); \ - if (ret < 0) \ - break; \ - } \ - ret; \ +#define __rsnd_mod_call(mod, func, rdai, io) \ +({ \ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ + struct device *dev = rsnd_priv_to_dev(priv); \ + dev_dbg(dev, "%s [%d] %s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + (mod)->ops->func(mod, rdai, io); \ +}) + +#define rsnd_mod_call(mod, func, rdai, io) \ + (!(mod) ? -ENODEV : \ + !((mod)->ops->func) ? 0 : \ + __rsnd_mod_call(mod, func, (rdai), (io))) + +#define rsnd_dai_call(rdai, io, fn) \ +({ \ + struct rsnd_mod *mod, *n; \ + int ret = 0; \ + for_each_rsnd_mod(mod, n, (io)) { \ + ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ + if (ret < 0) \ + break; \ + } \ + ret; \ }) int rsnd_dai_connect(struct rsnd_dai *rdai, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d4093907dfd8..fb1e0cee08b6 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -169,19 +169,6 @@ struct rsnd_mod { #define rsnd_mod_id(mod) ((mod)->id) #define for_each_rsnd_mod(pos, n, io) \ list_for_each_entry_safe(pos, n, &(io)->head, list) -#define __rsnd_mod_call(mod, func, rdai, io) \ -({ \ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ - struct device *dev = rsnd_priv_to_dev(priv); \ - dev_dbg(dev, "%s-%d-%s\n", \ - rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ - (mod)->ops->func(mod, rdai, io); \ -}) - -#define rsnd_mod_call(mod, func, rdai, io) \ - (!(mod) ? -ENODEV : \ - !((mod)->ops->func) ? 0 : \ - __rsnd_mod_call(mod, func, rdai, io)) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, -- cgit v1.2.3-55-g7522 From 5da39cf30454bbf3e92f56935e7d137e5bd2c830 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:00 -0800 Subject: ASoC: rsnd: remove verbose function parameter priv has rcar_snd_info pointer. having priv and info in same time is verbose. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 1 - sound/soc/sh/rcar/core.c | 11 +++++------ sound/soc/sh/rcar/gen.c | 7 ++----- sound/soc/sh/rcar/rsnd.h | 5 +---- sound/soc/sh/rcar/scu.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- 6 files changed, 10 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index af9e4407aa89..69d9394f3697 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -391,7 +391,6 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) } int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct rsnd_adg *adg; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 5f6d9fef23d1..b2370f68e645 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -577,7 +577,6 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { }; static int rsnd_dai_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; @@ -773,23 +772,23 @@ static int rsnd_probe(struct platform_device *pdev) /* * init each module */ - ret = rsnd_gen_probe(pdev, info, priv); + ret = rsnd_gen_probe(pdev, priv); if (ret) return ret; - ret = rsnd_ssi_probe(pdev, info, priv); + ret = rsnd_ssi_probe(pdev, priv); if (ret) return ret; - ret = rsnd_scu_probe(pdev, info, priv); + ret = rsnd_scu_probe(pdev, priv); if (ret) return ret; - ret = rsnd_adg_probe(pdev, info, priv); + ret = rsnd_adg_probe(pdev, priv); if (ret) return ret; - ret = rsnd_dai_probe(pdev, info, priv); + ret = rsnd_dai_probe(pdev, priv); if (ret) return ret; diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 0a43b906ffdf..bcb98f4be831 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -276,7 +276,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); @@ -374,7 +373,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); @@ -419,7 +417,6 @@ static int rsnd_gen1_probe(struct platform_device *pdev, * Gen */ int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -436,9 +433,9 @@ 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"); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index fb1e0cee08b6..8ac28acc7086 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -226,7 +226,6 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); * R-Car Gen1/Gen2 */ int rsnd_gen_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -248,7 +247,6 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -305,6 +303,7 @@ struct rsnd_priv { }; #define rsnd_priv_to_dev(priv) ((priv)->dev) +#define rsnd_priv_to_info(priv) ((priv)->info) #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) @@ -312,7 +311,6 @@ struct rsnd_priv { * R-Car SCU */ int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); @@ -327,7 +325,6 @@ unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, * R-Car SSI */ int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv); void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_priv *priv); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 3984d4b4f2df..82d8b20a6ffb 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -604,9 +604,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) } int rsnd_scu_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_scu *scu; struct rsnd_mod_ops *ops; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d3371d798d54..2460c9f564de 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -511,9 +511,9 @@ static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *s } int rsnd_ssi_probe(struct platform_device *pdev, - struct rcar_snd_info *info, struct rsnd_priv *priv) { + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_ssi_platform_info *pinfo; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; -- cgit v1.2.3-55-g7522 From 98455ed5ddbfbcbcd0adb300c6cb1964ed0a6931 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:07 -0800 Subject: ASoC: rsnd: remove verbose debug message from scu/ssi scu/ssi probe() already have more detail debug message. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 1 - sound/soc/sh/rcar/ssi.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 82d8b20a6ffb..882e837d39d1 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -663,7 +663,6 @@ int rsnd_scu_probe(struct platform_device *pdev, dev_dbg(dev, "SCU%d probed\n", i); } - dev_dbg(dev, "scu probed\n"); return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2460c9f564de..38a62a883b83 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -589,8 +589,6 @@ int rsnd_ssi_probe(struct platform_device *pdev, rsnd_ssi_parent_clk_setup(priv, ssi); } - dev_dbg(dev, "ssi probed\n"); - return 0; } -- cgit v1.2.3-55-g7522 From ecba9e724c5775aebd3a28e831643160c7146e83 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 24 Feb 2014 22:15:18 -0800 Subject: ASoC: rsnd: unify rdai naming struct rsnd_dai is called as "rdai", but its size has been called as "dai_nr". Unify these as "rdai" Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 8 ++++---- sound/soc/sh/rcar/rsnd.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index b2370f68e645..f0745af316be 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -352,7 +352,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) { int id = rdai - priv->rdai; - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return -EINVAL; return id; @@ -360,7 +360,7 @@ int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id) { - if ((id < 0) || (id >= rsnd_dai_nr(priv))) + if ((id < 0) || (id >= rsnd_rdai_nr(priv))) return NULL; return priv->rdai + id; @@ -607,7 +607,7 @@ static int rsnd_dai_probe(struct platform_device *pdev, return -ENOMEM; } - priv->dai_nr = dai_nr; + priv->rdai_nr = dai_nr; priv->daidrv = drv; priv->rdai = rdai; @@ -802,7 +802,7 @@ static int rsnd_probe(struct platform_device *pdev) } ret = snd_soc_register_component(dev, &rsnd_soc_component, - priv->daidrv, rsnd_dai_nr(priv)); + priv->daidrv, rsnd_rdai_nr(priv)); if (ret < 0) { dev_err(dev, "cannot snd dai register\n"); goto exit_snd_soc; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8ac28acc7086..3962a50977e5 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -202,10 +202,10 @@ struct rsnd_dai { unsigned int data_alignment:1; }; -#define rsnd_dai_nr(priv) ((priv)->dai_nr) +#define rsnd_rdai_nr(priv) ((priv)->rdai_nr) #define for_each_rsnd_dai(rdai, priv, i) \ for (i = 0; \ - (i < rsnd_dai_nr(priv)) && \ + (i < rsnd_rdai_nr(priv)) && \ ((rdai) = rsnd_dai_get(priv, i)); \ i++) @@ -299,7 +299,7 @@ struct rsnd_priv { */ struct snd_soc_dai_driver *daidrv; struct rsnd_dai *rdai; - int dai_nr; + int rdai_nr; }; #define rsnd_priv_to_dev(priv) ((priv)->dev) -- cgit v1.2.3-55-g7522 From e14de47ac95fb25818294325cd77d520c90c6ced Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:13 +0100 Subject: ASoC: pxa: Pass correct DAPM context to {corgi,poodle,spitz}_ext_control When calling {corgi,poodle,spitz}_ext_control() from the startup callback we pass the CODEC's DAPM context instead of the card's DAPM context. This is not a problem per se since all the DAPM functions in ext_control() fallback to widgets from other DAPM contexts, but passing the card's context is more consistent. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/corgi.c | 3 +-- sound/soc/pxa/poodle.c | 3 +-- sound/soc/pxa/spitz.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index b51f88002e62..916ff63d85d0 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -97,10 +97,9 @@ static void corgi_ext_control(struct snd_soc_dapm_context *dapm) static int corgi_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - corgi_ext_control(&codec->dapm); + corgi_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 27c6c03bc5d7..c6bdc6c0eff6 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -74,10 +74,9 @@ static void poodle_ext_control(struct snd_soc_dapm_context *dapm) static int poodle_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - poodle_ext_control(&codec->dapm); + poodle_ext_control(&rtd->card->dapm); return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 0728c1eb780c..d1b6bf9c8583 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -106,10 +106,9 @@ static void spitz_ext_control(struct snd_soc_dapm_context *dapm) static int spitz_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; /* check the jack status at stream startup */ - spitz_ext_control(&codec->dapm); + spitz_ext_control(&rtd->card->dapm); return 0; } -- cgit v1.2.3-55-g7522 From 23d8f2253c5ebe975465a61dd416a35b5ebda4b0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:14 +0100 Subject: ASoC: pxa: e740_wm9705: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/e740_wm9705.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c index 44b5c09d296b..c29fedab2f49 100644 --- a/sound/soc/pxa/e740_wm9705.c +++ b/sound/soc/pxa/e740_wm9705.c @@ -103,11 +103,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e740_dapm_widgets, - ARRAY_SIZE(e740_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -136,6 +131,11 @@ static struct snd_soc_card e740 = { .owner = THIS_MODULE, .dai_link = e740_dai, .num_links = ARRAY_SIZE(e740_dai), + + .dapm_widgets = e740_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e740_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e740_audio_gpios[] = { -- cgit v1.2.3-55-g7522 From 98308c825ba856796bf52b3c6d6955e62f1fc45c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:15 +0100 Subject: ASoC: pxa: e750_wm9705: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/e750_wm9705.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c index c34e447eb991..ee36aba88063 100644 --- a/sound/soc/pxa/e750_wm9705.c +++ b/sound/soc/pxa/e750_wm9705.c @@ -85,11 +85,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_nc_pin(dapm, "PCBEEP"); snd_soc_dapm_nc_pin(dapm, "MIC2"); - snd_soc_dapm_new_controls(dapm, e750_dapm_widgets, - ARRAY_SIZE(e750_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - return 0; } @@ -119,6 +114,11 @@ static struct snd_soc_card e750 = { .owner = THIS_MODULE, .dai_link = e750_dai, .num_links = ARRAY_SIZE(e750_dai), + + .dapm_widgets = e750_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e750_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e750_audio_gpios[] = { -- cgit v1.2.3-55-g7522 From 1bdd301f791e047ed36c18656890c0001f8ce5a3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:16 +0100 Subject: ASoC: pxa: e800_wm9712: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/e800_wm9712.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 3137f800b43f..24c2078ce70b 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c @@ -71,19 +71,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"MIC2", NULL, "Mic (Internal2)"}, }; -static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - - snd_soc_dapm_new_controls(dapm, e800_dapm_widgets, - ARRAY_SIZE(e800_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - return 0; -} - static struct snd_soc_dai_link e800_dai[] = { { .name = "AC97", @@ -92,7 +79,6 @@ static struct snd_soc_dai_link e800_dai[] = { .codec_dai_name = "wm9712-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm9712-codec", - .init = e800_ac97_init, }, { .name = "AC97 Aux", @@ -109,6 +95,11 @@ static struct snd_soc_card e800 = { .owner = THIS_MODULE, .dai_link = e800_dai, .num_links = ARRAY_SIZE(e800_dai), + + .dapm_widgets = e800_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(e800_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct gpio e800_audio_gpios[] = { -- cgit v1.2.3-55-g7522 From f6b2a04590bb3f7323a45b183956e63574d1f14b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:18 +0100 Subject: ASoC: pxa: mioa701_wm9713: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Also remove the snd_soc_dapm_enable_pin() calls, since pins are enabled by default and there are no matching snd_soc_dapm_disable_pin() calls. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/mioa701_wm9713.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c index 160c5245448f..595eee341e90 100644 --- a/sound/soc/pxa/mioa701_wm9713.c +++ b/sound/soc/pxa/mioa701_wm9713.c @@ -127,16 +127,8 @@ static const struct snd_soc_dapm_route audio_map[] = { static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; unsigned short reg; - /* Add mioa701 specific widgets */ - snd_soc_dapm_new_controls(dapm, mioa701_dapm_widgets, - ARRAY_SIZE(mioa701_dapm_widgets)); - - /* Set up mioa701 specific audio path audio_mapnects */ - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - /* Prepare GPIO8 for rear speaker amplifier */ reg = codec->driver->read(codec, AC97_GPIO_CFG); codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100); @@ -145,12 +137,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd) reg = codec->driver->read(codec, AC97_3D_CONTROL); codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000); - snd_soc_dapm_enable_pin(dapm, "Front Speaker"); - snd_soc_dapm_enable_pin(dapm, "Rear Speaker"); - snd_soc_dapm_enable_pin(dapm, "Front Mic"); - snd_soc_dapm_enable_pin(dapm, "GSM Line In"); - snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); - return 0; } @@ -183,6 +169,11 @@ static struct snd_soc_card mioa701 = { .owner = THIS_MODULE, .dai_link = mioa701_dai, .num_links = ARRAY_SIZE(mioa701_dai), + + .dapm_widgets = mioa701_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mioa701_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int mioa701_wm9713_probe(struct platform_device *pdev) -- cgit v1.2.3-55-g7522 From a9576cbbbafa2c687121638dadebfb136562a522 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Mar 2014 15:48:20 +0100 Subject: ASoC: pxa: zylonite: Convert to table based DAPM setup Use table based setup to register the DAPM widgets and routes. This on one hand makes the code a bit cleaner and on the other hand the board level DAPM elements get registered in the card's DAPM context rather than in the CODEC's DAPM context. Also drop the two snd_soc_dapm_enable_pin() since pins are enabled by default and there is no matching snd_soc_dapm_disable_pin() in the driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/pxa/zylonite.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index db8aadf8932d..23bf991e95d5 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c @@ -71,22 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = { static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; - struct snd_soc_dapm_context *dapm = &codec->dapm; - if (clk_pout) snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, clk_get_rate(pout), 0); - snd_soc_dapm_new_controls(dapm, zylonite_dapm_widgets, - ARRAY_SIZE(zylonite_dapm_widgets)); - - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); - - /* Static setup for now */ - snd_soc_dapm_enable_pin(dapm, "Headphone"); - snd_soc_dapm_enable_pin(dapm, "Headset Earpiece"); - return 0; } @@ -256,6 +244,11 @@ static struct snd_soc_card zylonite = { .resume_pre = &zylonite_resume_pre, .dai_link = zylonite_dai, .num_links = ARRAY_SIZE(zylonite_dai), + + .dapm_widgets = zylonite_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(zylonite_dapm_widgets), + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static struct platform_device *zylonite_snd_ac97_device; -- cgit v1.2.3-55-g7522 From 9bfed6cf4fa2cd2c5e80431244348b0c5d933cf5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:42:47 -0800 Subject: ASoC: rsnd: run rsnd_path_init() when probe() timing Current rsnd SSIU/SSI/SCU/SRU path is set when playback/capture starts up. But it is meaningless method, since the path is based on platform and can be set in probe() timing. This patch sets the path on probe() timing. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 94 +++++++++++++++++++++++++++++++++++++++--------- sound/soc/sh/rcar/gen.c | 56 ----------------------------- sound/soc/sh/rcar/rsnd.h | 9 ----- 3 files changed, 78 insertions(+), 81 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f0745af316be..96cb78612a7d 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -317,9 +317,9 @@ void rsnd_dma_quit(struct rsnd_priv *priv, ret; \ }) -int rsnd_dai_connect(struct rsnd_dai *rdai, - struct rsnd_mod *mod, - struct rsnd_dai_stream *io) +static int rsnd_dai_connect(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { if (!mod) return -EIO; @@ -340,7 +340,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, return 0; } -int rsnd_dai_disconnect(struct rsnd_mod *mod) +static int rsnd_dai_disconnect(struct rsnd_mod *mod) { list_del_init(&mod->list); mod->io = NULL; @@ -418,10 +418,6 @@ static int rsnd_dai_stream_init(struct rsnd_dai_stream *io, { struct snd_pcm_runtime *runtime = substream->runtime; - if (!list_empty(&io->head)) - return -EIO; - - INIT_LIST_HEAD(&io->head); io->substream = substream; io->byte_pos = 0; io->period_pos = 0; @@ -476,10 +472,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_init(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_dai_call(rdai, io, init); if (ret < 0) goto dai_trigger_end; @@ -497,10 +489,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end; - ret = rsnd_gen_path_exit(priv, rdai, io); - if (ret < 0) - goto dai_trigger_end; - ret = rsnd_platform_call(priv, dai, stop, ssi_id); if (ret < 0) goto dai_trigger_end; @@ -576,6 +564,70 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .set_fmt = rsnd_soc_dai_set_fmt, }; +static int rsnd_path_init(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod; + int ret; + int id; + + /* + * 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 + */ + /* get SSI's ID */ + mod = rsnd_ssi_mod_get_frm_dai(priv, + rsnd_dai_id(priv, rdai), + rsnd_dai_is_play(rdai, io)); + if (!mod) + return 0; + id = rsnd_mod_id(mod); + ret = 0; + + /* SCU */ + mod = rsnd_scu_mod_get(priv, id); + if (mod) { + ret = rsnd_dai_connect(rdai, mod, io); + if (ret < 0) + return ret; + } + + /* SSI */ + mod = rsnd_ssi_mod_get(priv, id); + if (mod) { + ret = rsnd_dai_connect(rdai, mod, io); + if (ret < 0) + return ret; + } + + return ret; +} + +static int rsnd_path_exit(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_mod *mod, *n; + int ret = 0; + + /* + * remove all mod from rdai + */ + for_each_rsnd_mod(mod, n, io) + ret |= rsnd_dai_disconnect(mod); + + return ret; +} + static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { @@ -634,12 +686,14 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].playback.formats = RSND_FMTS; drv[i].playback.channels_min = 2; drv[i].playback.channels_max = 2; + rsnd_path_init(priv, &rdai[i], &rdai[i].playback); } if (cmod) { drv[i].capture.rates = RSND_RATES; drv[i].capture.formats = RSND_FMTS; drv[i].capture.channels_min = 2; drv[i].capture.channels_max = 2; + rsnd_path_init(priv, &rdai[i], &rdai[i].capture); } dev_dbg(dev, "%s (%s/%s)\n", rdai[i].name, @@ -653,6 +707,14 @@ static int rsnd_dai_probe(struct platform_device *pdev, static void rsnd_dai_remove(struct platform_device *pdev, struct rsnd_priv *priv) { + struct rsnd_dai *rdai; + int i; + + for (i = 0; i < rsnd_rdai_nr(priv); i++) { + rdai = rsnd_dai_get(priv, i); + rsnd_path_exit(priv, rdai, &rdai->playback); + rsnd_path_exit(priv, rdai, &rdai->capture); + } } /* diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index bcb98f4be831..4f2c1d0c6970 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -155,62 +155,6 @@ 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; - - /* - * 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 - */ - - /* 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); - - /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - if (ret < 0) - return ret; - - /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - ret = rsnd_dai_connect(rdai, mod, io); - - return ret; -} - -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod, *n; - int ret = 0; - - /* - * remove all mod from rdai - */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); - - return ret; -} - /* * Gen2 */ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3962a50977e5..6a25203e0f08 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -210,9 +210,6 @@ struct rsnd_dai { i++) struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id); -int rsnd_dai_disconnect(struct rsnd_mod *mod); -int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, - struct rsnd_dai_stream *io); int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai); #define rsnd_dai_get_platform_info(rdai) ((rdai)->info) @@ -229,12 +226,6 @@ int rsnd_gen_probe(struct platform_device *pdev, struct rsnd_priv *priv); void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv); -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); -- cgit v1.2.3-55-g7522 From a126021d144bae88a563db2b57b0ad5eb1ee66d9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:42:55 -0800 Subject: ASoC: rsnd: use mod array instead of list on rdai struct rsnd_dai_stream used list for mod list. It added only odd flexibility to current driver, and it is a factor which makes extendibility difficult. rsnd use mod array instead of list from now. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 42 +++++++++++++++++++++++------------------- sound/soc/sh/rcar/rsnd.h | 12 ++++++++---- sound/soc/sh/rcar/scu.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- 4 files changed, 33 insertions(+), 25 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 96cb78612a7d..416b0782503a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -121,12 +121,13 @@ char *rsnd_mod_name(struct rsnd_mod *mod) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id) { mod->priv = priv; mod->id = id; mod->ops = ops; - INIT_LIST_HEAD(&mod->list); + mod->type = type; } /* @@ -307,9 +308,12 @@ void rsnd_dma_quit(struct rsnd_priv *priv, #define rsnd_dai_call(rdai, io, fn) \ ({ \ - struct rsnd_mod *mod, *n; \ - int ret = 0; \ - for_each_rsnd_mod(mod, n, (io)) { \ + struct rsnd_mod *mod; \ + int ret = 0, i; \ + for (i = 0; i < RSND_MOD_MAX; i++) { \ + mod = (io)->mod[i]; \ + if (!mod) \ + continue; \ ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ if (ret < 0) \ break; \ @@ -317,14 +321,13 @@ void rsnd_dma_quit(struct rsnd_priv *priv, ret; \ }) -static int rsnd_dai_connect(struct rsnd_dai *rdai, - struct rsnd_mod *mod, +static int rsnd_dai_connect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { if (!mod) return -EIO; - if (!list_empty(&mod->list)) { + if (io->mod[mod->type]) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); @@ -334,15 +337,15 @@ static int rsnd_dai_connect(struct rsnd_dai *rdai, return -EIO; } - list_add_tail(&mod->list, &io->head); + io->mod[mod->type] = mod; mod->io = io; return 0; } -static int rsnd_dai_disconnect(struct rsnd_mod *mod) +static int rsnd_dai_disconnect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { - list_del_init(&mod->list); + io->mod[mod->type] = NULL; mod->io = NULL; return 0; @@ -596,7 +599,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, /* SCU */ mod = rsnd_scu_mod_get(priv, id); if (mod) { - ret = rsnd_dai_connect(rdai, mod, io); + ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } @@ -604,7 +607,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, /* SSI */ mod = rsnd_ssi_mod_get(priv, id); if (mod) { - ret = rsnd_dai_connect(rdai, mod, io); + ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } @@ -616,14 +619,18 @@ static int rsnd_path_exit(struct rsnd_priv *priv, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_mod *mod, *n; - int ret = 0; + struct rsnd_mod *mod; + int ret = 0, i; /* * remove all mod from rdai */ - for_each_rsnd_mod(mod, n, io) - ret |= rsnd_dai_disconnect(mod); + for (i = 0; i < RSND_MOD_MAX; i++) { + mod = io->mod[i]; + if (!mod) + continue; + ret |= rsnd_dai_disconnect(mod, io); + } return ret; } @@ -671,9 +678,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, /* * init rsnd_dai */ - INIT_LIST_HEAD(&rdai[i].playback.head); - INIT_LIST_HEAD(&rdai[i].capture.head); - snprintf(rdai[i].name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", i); /* diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 6a25203e0f08..7767a8f1994a 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -135,6 +135,11 @@ void rsnd_dma_quit(struct rsnd_priv *priv, /* * R-Car sound mod */ +enum rsnd_mod_type { + RSND_MOD_SCU = 0, + RSND_MOD_SSI, + RSND_MOD_MAX, +}; struct rsnd_mod_ops { char *name; @@ -155,9 +160,9 @@ struct rsnd_mod_ops { struct rsnd_dai_stream; struct rsnd_mod { int id; + enum rsnd_mod_type type; struct rsnd_priv *priv; struct rsnd_mod_ops *ops; - struct list_head list; /* connect to rsnd_dai playback/capture */ struct rsnd_dma dma; struct rsnd_dai_stream *io; }; @@ -167,12 +172,11 @@ struct rsnd_mod { #define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) #define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) -#define for_each_rsnd_mod(pos, n, io) \ - list_for_each_entry_safe(pos, n, &(io)->head, list) void rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, + enum rsnd_mod_type type, int id); char *rsnd_mod_name(struct rsnd_mod *mod); @@ -181,8 +185,8 @@ char *rsnd_mod_name(struct rsnd_mod *mod); */ #define RSND_DAI_NAME_SIZE 16 struct rsnd_dai_stream { - struct list_head head; /* head of rsnd_mod list */ struct snd_pcm_substream *substream; + struct rsnd_mod *mod[RSND_MOD_MAX]; int byte_pos; int period_pos; int byte_per_period; diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 882e837d39d1..81264ecd82ac 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -659,7 +659,7 @@ int rsnd_scu_probe(struct platform_device *pdev, ops = &rsnd_scu_non_gen2_ops; } - rsnd_mod_init(priv, &scu->mod, ops, i); + rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); dev_dbg(dev, "SCU%d probed\n", i); } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 38a62a883b83..480dde5076b7 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -584,7 +584,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, dev_dbg(dev, "SSI%d use PIO transfer\n", i); } - rsnd_mod_init(priv, &ssi->mod, ops, i); + rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); rsnd_ssi_parent_clk_setup(priv, ssi); } -- cgit v1.2.3-55-g7522 From 374e5426377604a94d672650ef22dd2b4285de17 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:03 -0800 Subject: ASoC: rsnd: get ssi/scu from rsnd_dai_stream Current driver is assuming that SSI id = SCU id. But, now, it can get correct SSI/SCU from rsnd_dai_stream. use it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 4 +++- sound/soc/sh/rcar/scu.c | 20 +++++++++++--------- sound/soc/sh/rcar/ssi.c | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 7767a8f1994a..cbc38a2be81c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -192,6 +192,8 @@ struct rsnd_dai_stream { int byte_per_period; int next_period_byte; }; +#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) +#define rsnd_io_to_mod_scu(io) ((io)->mod[RSND_MOD_SCU]) struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -311,7 +313,7 @@ void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); #define rsnd_scu_nr(priv) ((priv)->scu_nr) diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 81264ecd82ac..1073d35486e3 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -121,7 +121,8 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int id = rsnd_mod_id(mod); + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + int ssi_id = rsnd_mod_id(ssi_mod); u32 convert_rate = rsnd_scu_convert_rate(scu); if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { @@ -134,15 +135,15 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, /* * SSI_MODE0 */ - rsnd_mod_bset(mod, SSI_MODE0, (1 << id), - rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << id)); + rsnd_mod_bset(mod, SSI_MODE0, (1 << ssi_id), + rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << ssi_id)); /* * SSI_MODE1 */ - if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { + if (rsnd_ssi_is_pin_sharing(ssi_mod)) { int shift = -1; - switch (id) { + switch (ssi_id) { case 1: shift = 0; break; @@ -165,14 +166,13 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, } unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) { struct rsnd_scu *scu; unsigned int rate; - /* this function is assuming SSI id = SCU id here */ - scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod))); + scu = rsnd_mod_to_scu(rsnd_io_to_mod_scu(io)); /* * return convert rate if SRC is used, @@ -583,8 +583,10 @@ static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + /* enable PIO interrupt */ - rsnd_mod_write(mod, INT_ENABLE, 0x0f000000); + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 480dde5076b7..25a7d441f8fc 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -121,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; - unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime); + unsigned int rate = rsnd_scu_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG -- cgit v1.2.3-55-g7522 From 468be93eb4e28c5710ed8acc1b938937707e537c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:11 -0800 Subject: ASoC: rsnd: use devm_clk_get() instead of clk_get() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 69d9394f3697..a05ad8159824 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -405,11 +405,11 @@ int rsnd_adg_probe(struct platform_device *pdev, return -ENOMEM; } - clk_orig = clk_get(dev, NULL); - adg->clk[CLKA] = clk_get(dev, "clk_a"); - adg->clk[CLKB] = clk_get(dev, "clk_b"); - adg->clk[CLKC] = clk_get(dev, "clk_c"); - adg->clk[CLKI] = clk_get(dev, "clk_i"); + clk_orig = devm_clk_get(dev, NULL); + adg->clk[CLKA] = devm_clk_get(dev, "clk_a"); + adg->clk[CLKB] = devm_clk_get(dev, "clk_b"); + adg->clk[CLKC] = devm_clk_get(dev, "clk_c"); + adg->clk[CLKI] = devm_clk_get(dev, "clk_i"); /* * It request device dependent audio clock. @@ -432,10 +432,10 @@ int rsnd_adg_probe(struct platform_device *pdev, * but will be removed soon */ if (use_old_style) { - adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); - adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); - adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); - adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); + adg->clk[CLKA] = devm_clk_get(NULL, "audio_clk_a"); + adg->clk[CLKB] = devm_clk_get(NULL, "audio_clk_b"); + adg->clk[CLKC] = devm_clk_get(NULL, "audio_clk_c"); + adg->clk[CLKI] = devm_clk_get(NULL, "audio_clk_internal"); } for_each_rsnd_clk(clk, adg, i) { @@ -457,10 +457,4 @@ int rsnd_adg_probe(struct platform_device *pdev, void rsnd_adg_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_adg *adg = priv->adg; - struct clk *clk; - int i; - - for_each_rsnd_clk(clk, adg, i) - clk_put(clk); } -- cgit v1.2.3-55-g7522 From d1ac970f5de94bef9e094b46f016899d04e8178b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:18 -0800 Subject: ASoC: rsnd: use function pointer for each probe R-Car sound consists of many devices. It will have more device support in the future. Thus, for each probe become now function pointer array. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 416b0782503a..ea747614fbf8 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -814,7 +814,15 @@ static int rsnd_probe(struct platform_device *pdev) struct rcar_snd_info *info; struct rsnd_priv *priv; struct device *dev = &pdev->dev; - int ret; + int (*probe_func[])(struct platform_device *pdev, + struct rsnd_priv *priv) = { + rsnd_gen_probe, + rsnd_ssi_probe, + rsnd_scu_probe, + rsnd_adg_probe, + rsnd_dai_probe, + }; + int ret, i; info = pdev->dev.platform_data; if (!info) { @@ -838,25 +846,11 @@ static int rsnd_probe(struct platform_device *pdev) /* * init each module */ - ret = rsnd_gen_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_ssi_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_scu_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_adg_probe(pdev, priv); - if (ret) - return ret; - - ret = rsnd_dai_probe(pdev, priv); - if (ret) - return ret; + for (i = 0; i < ARRAY_SIZE(probe_func); i++) { + ret = probe_func[i](pdev, priv); + if (ret) + return ret; + } /* * asoc register -- cgit v1.2.3-55-g7522 From 685fb3eb31445bd872ab30ae301404b2cac7cd75 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:26 -0800 Subject: ASoC: rsnd: remove unused SSI_CONTROL Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 1 - sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 4f2c1d0c6970..92d1bc9acef0 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -173,7 +173,6 @@ 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_S_REG(gen, SSIU, SSI_CONTROL, 0x810), 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), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index cbc38a2be81c..e16acd2037a0 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -39,7 +39,6 @@ enum rsnd_reg { RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ RSND_REG_SRC_CTRL, /* for Gen2 */ RSND_REG_SSI_CTRL, /* for Gen2 */ - RSND_REG_SSI_CONTROL, RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, -- cgit v1.2.3-55-g7522 From 8467dedc9dae3630a2ede49a43120af3ed54ba19 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:33 -0800 Subject: ASoC: rsnd: modify rsnd_adg_ssi_ws_timing_gen2() parameter rsnd_adg_ssi_ws_timing_gen2() returns SSI WS timing, and it used "mod" as parameter. but, this "mod" is sometimes not ssi mod. Get SSI mod from rsnd_dai_stream Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index a05ad8159824..8df00ac3b120 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -32,8 +32,9 @@ struct rsnd_adg { #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_mod *mod) +static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) { + struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); int id = rsnd_mod_id(mod); int ws = id; @@ -67,7 +68,7 @@ static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, u32 mask, ws; u32 in, out; - ws = rsnd_adg_ssi_ws_timing_gen2(mod); + ws = rsnd_adg_ssi_ws_timing_gen2(io); in = (is_play) ? timsel : ws; out = (is_play) ? ws : timsel; @@ -174,7 +175,7 @@ int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - u32 val = rsnd_adg_ssi_ws_timing_gen2(mod); + u32 val = rsnd_adg_ssi_ws_timing_gen2(io); return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); } -- cgit v1.2.3-55-g7522 From c82e1c8874e5abaf52f9ed886386cbe08ec98a5b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 2 Mar 2014 23:43:40 -0800 Subject: ASoC: rsnd: share reg_field and reduce memory Gen1/Gen2 code never be used in same time. Thus, driver can share Gen1 only register and Gen2 only register. It can reduce memory too. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 81 +++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 28 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e16acd2037a0..d5afdee6b6f2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -32,18 +32,8 @@ */ enum rsnd_reg { /* SRU/SCU/SSIU */ - RSND_REG_SRC_ROUTE_SEL, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL0, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ - RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ - RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ - RSND_REG_SRC_CTRL, /* for Gen2 */ - RSND_REG_SSI_CTRL, /* for Gen2 */ - RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ - RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, - RSND_REG_INT_ENABLE, /* for Gen2 */ RSND_REG_SRC_BUSIF_MODE, RSND_REG_SRC_ROUTE_MODE0, RSND_REG_SRC_SWRSR, @@ -52,9 +42,6 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, - RSND_REG_SRC_MNFSR, /* for Gen1 */ - RSND_REG_SRC_BSDSR, /* for Gen2 */ - RSND_REG_SRC_BSISR, /* for Gen2 */ /* ADG */ RSND_REG_BRRA, @@ -62,21 +49,6 @@ enum rsnd_reg { RSND_REG_SSICKR, RSND_REG_AUDIO_CLK_SEL0, RSND_REG_AUDIO_CLK_SEL1, - RSND_REG_AUDIO_CLK_SEL2, - RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ - RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ - RSND_REG_DIV_EN, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ - RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ - RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ /* SSI */ RSND_REG_SSICR, @@ -85,9 +57,62 @@ enum rsnd_reg { RSND_REG_SSIRDR, RSND_REG_SSIWSR, + /* SHARE see below */ + RSND_REG_SHARE01, + RSND_REG_SHARE02, + RSND_REG_SHARE03, + RSND_REG_SHARE04, + RSND_REG_SHARE05, + RSND_REG_SHARE06, + RSND_REG_SHARE07, + RSND_REG_SHARE08, + RSND_REG_SHARE09, + RSND_REG_SHARE10, + RSND_REG_SHARE11, + RSND_REG_SHARE12, + RSND_REG_SHARE13, + RSND_REG_SHARE14, + RSND_REG_SHARE15, + RSND_REG_SHARE16, + RSND_REG_SHARE17, + RSND_REG_SHARE18, + RSND_REG_SHARE19, + RSND_REG_MAX, }; +/* Gen1 only */ +#define RSND_REG_SRC_ROUTE_SEL RSND_REG_SHARE01 +#define RSND_REG_SRC_TMG_SEL0 RSND_REG_SHARE02 +#define RSND_REG_SRC_TMG_SEL1 RSND_REG_SHARE03 +#define RSND_REG_SRC_TMG_SEL2 RSND_REG_SHARE04 +#define RSND_REG_SRC_ROUTE_CTRL RSND_REG_SHARE05 +#define RSND_REG_SRC_MNFSR RSND_REG_SHARE06 +#define RSND_REG_AUDIO_CLK_SEL3 RSND_REG_SHARE07 +#define RSND_REG_AUDIO_CLK_SEL4 RSND_REG_SHARE08 +#define RSND_REG_AUDIO_CLK_SEL5 RSND_REG_SHARE09 + +/* Gen2 only */ +#define RSND_REG_SRC_CTRL RSND_REG_SHARE01 +#define RSND_REG_SSI_CTRL RSND_REG_SHARE02 +#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03 +#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04 +#define RSND_REG_INT_ENABLE RSND_REG_SHARE05 +#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06 +#define RSND_REG_SRC_BSISR RSND_REG_SHARE07 +#define RSND_REG_DIV_EN RSND_REG_SHARE08 +#define RSND_REG_SRCIN_TIMSEL0 RSND_REG_SHARE09 +#define RSND_REG_SRCIN_TIMSEL1 RSND_REG_SHARE10 +#define RSND_REG_SRCIN_TIMSEL2 RSND_REG_SHARE11 +#define RSND_REG_SRCIN_TIMSEL3 RSND_REG_SHARE12 +#define RSND_REG_SRCIN_TIMSEL4 RSND_REG_SHARE13 +#define RSND_REG_SRCOUT_TIMSEL0 RSND_REG_SHARE14 +#define RSND_REG_SRCOUT_TIMSEL1 RSND_REG_SHARE15 +#define RSND_REG_SRCOUT_TIMSEL2 RSND_REG_SHARE16 +#define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 +#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 +#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 + struct rsnd_priv; struct rsnd_mod; struct rsnd_dai; -- cgit v1.2.3-55-g7522 From 78f13d0c5a2888564b2bed7f8433c8ec889997ff Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:49:50 -0800 Subject: ASoC: rsnd: add struct rsnd_dai_platform_info R-Car sound DAI consists from SSI/SCU/SSIU/SRU... Current R-Car sound DAI is decided from these settings, but it is intuitively unclear, and is not good design for DT support. This patch adds new rsnd_dai_platform_info to solve this issue. But now, many platform is using this driver without rsnd_dai_platform_info. So, this patch still supports DAI settings via SSI to keep compatible. It will be removed in next Linux version. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 17 ++++++++++++++++- sound/soc/sh/rcar/core.c | 23 ++++++++++++++++------- sound/soc/sh/rcar/ssi.c | 14 ++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index e3d585c67685..698f7b5fc76d 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -36,13 +36,15 @@ #define RSND_SSI_CLK_PIN_SHARE (1 << 31) #define RSND_SSI_PLAY (1 << 24) +#define RSND_SSI(_dma_id, _pio_irq, _flags) \ +{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_SET(_dai_id, _dma_id, _pio_irq, _flags) \ { .dai_id = _dai_id, .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags } #define RSND_SSI_UNUSED \ { .dai_id = -1, .dma_id = -1, .pio_irq = -1, .flags = 0 } struct rsnd_ssi_platform_info { - int dai_id; + int dai_id; /* will be removed */ int dma_id; int pio_irq; u32 flags; @@ -53,6 +55,8 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ +#define RSND_SCU(rate, _dma_id) \ +{ .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } #define RSND_SCU_SET(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } #define RSND_SCU_UNUSED \ @@ -64,6 +68,15 @@ struct rsnd_scu_platform_info { int dma_id; /* for Gen2 SCU */ }; +struct rsnd_dai_path_info { + struct rsnd_ssi_platform_info *ssi; +}; + +struct rsnd_dai_platform_info { + struct rsnd_dai_path_info playback; + struct rsnd_dai_path_info capture; +}; + /* * flags * @@ -81,6 +94,8 @@ struct rcar_snd_info { int ssi_info_nr; struct rsnd_scu_platform_info *scu_info; int scu_info_nr; + struct rsnd_dai_platform_info *dai_info; + int dai_info_nr; int (*start)(int id); int (*stop)(int id); }; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ea747614fbf8..450472633eb1 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -639,19 +639,26 @@ static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { struct snd_soc_dai_driver *drv; + struct rcar_snd_info *info = rsnd_priv_to_info(priv); struct rsnd_dai *rdai; struct rsnd_mod *pmod, *cmod; struct device *dev = rsnd_priv_to_dev(priv); - int dai_nr; + int dai_nr = info->dai_info_nr; int i; - /* get max dai nr */ - for (dai_nr = 0; dai_nr < 32; dai_nr++) { - pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); - cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); + /* + * dai_nr should be set via dai_info_nr, + * but allow it to keeping compatible + */ + if (!dai_nr) { + /* get max dai nr */ + for (dai_nr = 0; dai_nr < 32; dai_nr++) { + pmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 1); + cmod = rsnd_ssi_mod_get_frm_dai(priv, dai_nr, 0); - if (!pmod && !cmod) - break; + if (!pmod && !cmod) + break; + } } if (!dai_nr) { @@ -671,6 +678,8 @@ static int rsnd_dai_probe(struct platform_device *pdev, priv->rdai = rdai; for (i = 0; i < dai_nr; i++) { + if (info->dai_info) + rdai[i].info = &info->dai_info[i]; pmod = rsnd_ssi_mod_get_frm_dai(priv, i, 1); cmod = rsnd_ssi_mod_get_frm_dai(priv, i, 0); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 25a7d441f8fc..34234813f742 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -451,12 +451,26 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = { struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play) { + struct rsnd_dai_platform_info *dai_info = NULL; + struct rsnd_dai_path_info *path_info = NULL; + struct rsnd_ssi_platform_info *target_info = NULL; struct rsnd_ssi *ssi; int i, has_play; + if (priv->rdai) + dai_info = priv->rdai[dai_id].info; + if (dai_info) + path_info = (is_play) ? &dai_info->playback : &dai_info->capture; + if (path_info) + target_info = path_info->ssi; + is_play = !!is_play; for_each_rsnd_ssi(ssi, priv, i) { + if (target_info == ssi->info) + return &ssi->mod; + + /* for compatible */ if (rsnd_ssi_dai_id(ssi) != dai_id) continue; -- cgit v1.2.3-55-g7522 From 389933d9f6e55a1ef3a71549c36f6283b9f8c145 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:00 -0800 Subject: ASoC: rsnd: Get correct SCU ID Current rsnd driver is assuming that SCU/SRU ID is same as SSIU/SSI ID, because Gen1 can't select it. But, Gen2 can select it. The SCU/SRU/SSIU/SSI pair depends on the platform. This patch get correct SCU ID from platform info. To keep compatible, it still assuming SCU ID = SSI ID if platform doesn't have info Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 1 + sound/soc/sh/rcar/core.c | 47 +++++++++++++++++++++++++++++++++-------------- sound/soc/sh/rcar/rsnd.h | 14 ++++++++++++++ sound/soc/sh/rcar/scu.c | 21 ++++++++++++++++----- sound/soc/sh/rcar/ssi.c | 9 ++++++++- 5 files changed, 72 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 698f7b5fc76d..1d8c68323f49 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -70,6 +70,7 @@ struct rsnd_scu_platform_info { struct rsnd_dai_path_info { struct rsnd_ssi_platform_info *ssi; + struct rsnd_scu_platform_info *scu; }; struct rsnd_dai_platform_info { diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 450472633eb1..7316d10e4649 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -107,6 +107,11 @@ (!(priv->info->func) ? 0 : \ priv->info->func(param)) +#define rsnd_is_enable_path(io, name) \ + ((io)->info ? (io)->info->name : NULL) +#define rsnd_info_id(priv, io, name) \ + ((io)->info->name - priv->info->name##_info) + /* * rsnd_mod functions */ @@ -572,8 +577,10 @@ static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai_stream *io) { struct rsnd_mod *mod; + struct rsnd_dai_platform_info *dai_info = rdai->info; int ret; - int id; + int ssi_id = -1; + int scu_id = -1; /* * Gen1 is created by SRU/SSI, and this SRU is base module of @@ -584,29 +591,35 @@ static int rsnd_path_init(struct rsnd_priv *priv, * * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is * using fixed path. - * - * Then, SSI id = SCU id here */ - /* get SSI's ID */ - mod = rsnd_ssi_mod_get_frm_dai(priv, - rsnd_dai_id(priv, rdai), - rsnd_dai_is_play(rdai, io)); - if (!mod) - return 0; - id = rsnd_mod_id(mod); + if (dai_info) { + if (rsnd_is_enable_path(io, ssi)) + ssi_id = rsnd_info_id(priv, io, ssi); + if (rsnd_is_enable_path(io, scu)) + scu_id = rsnd_info_id(priv, io, scu); + } else { + /* get SSI's ID */ + mod = rsnd_ssi_mod_get_frm_dai(priv, + rsnd_dai_id(priv, rdai), + rsnd_dai_is_play(rdai, io)); + if (!mod) + return 0; + ssi_id = scu_id = rsnd_mod_id(mod); + } + ret = 0; /* SCU */ - mod = rsnd_scu_mod_get(priv, id); - if (mod) { + if (scu_id >= 0) { + mod = rsnd_scu_mod_get(priv, scu_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; } /* SSI */ - mod = rsnd_ssi_mod_get(priv, id); - if (mod) { + if (ssi_id >= 0) { + mod = rsnd_ssi_mod_get(priv, ssi_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; @@ -699,6 +712,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].playback.formats = RSND_FMTS; drv[i].playback.channels_min = 2; drv[i].playback.channels_max = 2; + + if (info->dai_info) + rdai[i].playback.info = &info->dai_info[i].playback; rsnd_path_init(priv, &rdai[i], &rdai[i].playback); } if (cmod) { @@ -706,6 +722,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, drv[i].capture.formats = RSND_FMTS; drv[i].capture.channels_min = 2; drv[i].capture.channels_max = 2; + + if (info->dai_info) + rdai[i].capture.info = &info->dai_info[i].capture; rsnd_path_init(priv, &rdai[i], &rdai[i].capture); } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d5afdee6b6f2..3472631c7b35 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -211,6 +211,7 @@ char *rsnd_mod_name(struct rsnd_mod *mod); struct rsnd_dai_stream { struct snd_pcm_substream *substream; struct rsnd_mod *mod[RSND_MOD_MAX]; + struct rsnd_dai_path_info *info; /* rcar_snd.h */ int byte_pos; int period_pos; int byte_per_period; @@ -328,6 +329,19 @@ struct rsnd_priv { #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) +#define rsnd_info_is_playback(priv, type) \ +({ \ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); \ + int i, is_play = 0; \ + for (i = 0; i < info->dai_info_nr; i++) { \ + if (info->dai_info[i].playback.type == (type)->info) { \ + is_play = 1; \ + break; \ + } \ + } \ + is_play; \ +}) + /* * R-Car SCU */ diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 1073d35486e3..b517300f32ce 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -620,6 +620,9 @@ int rsnd_scu_probe(struct platform_device *pdev, * init SCU */ nr = info->scu_info_nr; + if (!nr) + return 0; + scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); if (!scu) { dev_err(dev, "SCU allocate failed\n"); @@ -644,11 +647,19 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; if (rsnd_is_gen2(priv)) { - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); - int ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(&scu->mod), - rsnd_ssi_is_play(ssi), - scu->info->dma_id); + int ret; + int is_play; + + if (info->dai_info) { + is_play = rsnd_info_is_playback(priv, scu); + } else { + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); + is_play = rsnd_ssi_is_play(ssi); + } + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(&scu->mod), + is_play, + scu->info->dma_id); if (ret < 0) return ret; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 34234813f742..9162c2bb6cc5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -567,9 +567,16 @@ int rsnd_ssi_probe(struct platform_device *pdev, * SSI DMA case */ if (pinfo->dma_id > 0) { + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, ssi); + else + is_play = rsnd_ssi_is_play(&ssi->mod); + ret = rsnd_dma_init( priv, rsnd_mod_to_dma(&ssi->mod), - rsnd_ssi_is_play(&ssi->mod), + is_play, pinfo->dma_id); if (ret < 0) dev_info(dev, "SSI DMA failed. try PIO transter\n"); -- cgit v1.2.3-55-g7522 From b8cc41e9e8cc5beec9dcbe044cfc44aa0325d9e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:08 -0800 Subject: ASoC: rsnd: add rsnd_scu_enable_ssi_irq() Current R-Car sound driver is assuming that SCU mod is used even though it is not needed. Because scu.c is controlling SSIU too. (it is Gen1 compatibility) But, SCU mod will be really not used if new platform dai feature was used. Thus, SSIU irq setting is called from SSI directory by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 3 +++ sound/soc/sh/rcar/scu.c | 26 +++++++++++++------------- sound/soc/sh/rcar/ssi.c | 2 ++ 3 files changed, 18 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3472631c7b35..3b71b77c4fd8 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -353,6 +353,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); +int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); #define rsnd_scu_nr(priv) ((priv)->scu_nr) diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index b517300f32ce..8ce79e855cf0 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -165,6 +165,19 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, return 0; } +int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + + /* enable PIO interrupt if Gen2 */ + if (rsnd_is_gen2(priv)) + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); + + return 0; +} + unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) @@ -579,22 +592,9 @@ static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .stop = rsnd_scu_stop_gen2, }; -static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); - - /* enable PIO interrupt */ - rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); - - return 0; -} - static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { .name = "non-scu (gen2)", .init = rsnd_scu_ssi_mode_init, - .start = rsnd_scu_start_non_gen2, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 9162c2bb6cc5..a74c7a789b2b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -365,6 +365,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; + rsnd_scu_enable_ssi_irq(mod, rdai, io); + rsnd_ssi_hw_start(ssi, rdai, io); return 0; -- cgit v1.2.3-55-g7522 From 221bf523e31306c1095b28932e079950108e3887 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:24 -0800 Subject: ASoC: rsnd: call rsnd_scu_ssi_mode_init() from SSI Current R-Car sound driver is assuming that SCU mod is used even though it is not needed. Because scu.c is controlling SSIU too. (it is Gen1 compatibility) But, SCU mod will be really not used if new platform dai feature was added. Thus, rsnd_scu_ssi_mode_init() is called from SSI directory by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 3 +++ sound/soc/sh/rcar/scu.c | 54 +++++++++++++++--------------------------------- sound/soc/sh/rcar/ssi.c | 2 ++ 3 files changed, 22 insertions(+), 37 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3b71b77c4fd8..9205f96da2f4 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -353,6 +353,9 @@ struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); +int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 8ce79e855cf0..63e6aeb8c42d 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -115,28 +115,28 @@ struct rsnd_scu { /* * Gen1/Gen2 common functions */ -static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_mod *scu_mod = rsnd_io_to_mod_scu(io); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); int ssi_id = rsnd_mod_id(ssi_mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - - if (convert_rate && !rsnd_dai_is_clk_master(rdai)) { - struct device *dev = rsnd_priv_to_dev(priv); - - dev_err(dev, "rsnd should be clk master when you rate convert\n"); - return -EINVAL; - } + int has_scu = 0; /* * SSI_MODE0 */ - rsnd_mod_bset(mod, SSI_MODE0, (1 << ssi_id), - rsnd_scu_hpbif_is_enable(scu) ? 0 : (1 << ssi_id)); + if (info->dai_info) { + has_scu = !!scu_mod; + } else { + struct rsnd_scu *scu = rsnd_mod_to_scu(scu_mod); + has_scu = rsnd_scu_hpbif_is_enable(scu); + } + + rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), + has_scu ? 0 : (1 << ssi_id)); /* * SSI_MODE1 @@ -156,7 +156,7 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod, } if (shift >= 0) - rsnd_mod_bset(mod, SSI_MODE1, + rsnd_mod_bset(ssi_mod, SSI_MODE1, 0x3 << shift, rsnd_dai_is_clk_master(rdai) ? 0x2 << shift : 0x1 << shift); @@ -253,14 +253,9 @@ static int rsnd_scu_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - int ret; clk_enable(scu->clk); - ret = rsnd_scu_ssi_mode_init(mod, rdai, io); - if (ret < 0) - return ret; - return 0; } @@ -487,11 +482,6 @@ static struct rsnd_mod_ops rsnd_scu_gen1_ops = { .stop = rsnd_scu_stop_gen1, }; -static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { - .name = "non-sru (gen1)", - .init = rsnd_scu_ssi_mode_init, -}; - /* * Gen2 functions */ @@ -592,11 +582,6 @@ static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .stop = rsnd_scu_stop_gen2, }; -static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = { - .name = "non-scu (gen2)", - .init = rsnd_scu_ssi_mode_init, -}; - struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) { if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) @@ -665,11 +650,6 @@ int rsnd_scu_probe(struct platform_device *pdev, ops = &rsnd_scu_gen2_ops; } - } else { - if (rsnd_is_gen1(priv)) - ops = &rsnd_scu_non_gen1_ops; - if (rsnd_is_gen2(priv)) - ops = &rsnd_scu_non_gen2_ops; } rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index a74c7a789b2b..a7df216a46da 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -287,6 +287,8 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ + rsnd_scu_ssi_mode_init(mod, rdai, io); + return 0; } -- cgit v1.2.3-55-g7522 From 7681f6ac6b6338932621f842d68e54f6267b785f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:33 -0800 Subject: ASoC: rsnd: add probe/remove callback on rsnd_mod_ops Each rsnd mod needs specific probe method, and its best timing is DAI probe timing. But current code runs it mod probe timing. This patch adds new probe/remove callback to solve it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 23 +++++++++++++++++++++++ sound/soc/sh/rcar/rsnd.h | 6 ++++++ 2 files changed, 29 insertions(+) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 7316d10e4649..e8e585de7251 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -842,6 +842,7 @@ static int rsnd_probe(struct platform_device *pdev) struct rcar_snd_info *info; struct rsnd_priv *priv; struct device *dev = &pdev->dev; + struct rsnd_dai *rdai; int (*probe_func[])(struct platform_device *pdev, struct rsnd_priv *priv) = { rsnd_gen_probe, @@ -880,6 +881,16 @@ static int rsnd_probe(struct platform_device *pdev) return ret; } + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, probe); + if (ret) + return ret; + + ret = rsnd_dai_call(rdai, &rdai->capture, probe); + if (ret) + return ret; + } + /* * asoc register */ @@ -912,9 +923,21 @@ exit_snd_soc: static int rsnd_remove(struct platform_device *pdev) { struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); + struct rsnd_dai *rdai; + int ret, i; pm_runtime_disable(&pdev->dev); + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(rdai, &rdai->playback, remove); + if (ret) + return ret; + + ret = rsnd_dai_call(rdai, &rdai->capture, remove); + if (ret) + return ret; + } + /* * remove each module */ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9205f96da2f4..db20b3721953 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -167,6 +167,12 @@ enum rsnd_mod_type { struct rsnd_mod_ops { char *name; + int (*probe)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); + int (*remove)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io); int (*init)(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -- cgit v1.2.3-55-g7522 From 76c6fb5c49790da44d553f655182b426ade2c599 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:41 -0800 Subject: ASoC: rsnd: use mod probe method on SCU Now, it can use .probe Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 64 ++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 63e6aeb8c42d..40250acf608d 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -525,6 +525,42 @@ static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, return ret; } +static int rsnd_scu_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); + struct device *dev = rsnd_priv_to_dev(priv); + int ret; + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, scu); + else + is_play = rsnd_ssi_is_play(ssi); + + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(mod), + is_play, + scu->info->dma_id); + if (ret < 0) + dev_err(dev, "SCU DMA failed\n"); + + return ret; +} + +static int rsnd_scu_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + static int rsnd_scu_init_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -576,6 +612,8 @@ static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_scu_gen2_ops = { .name = "scu (gen2)", + .probe = rsnd_scu_probe_gen2, + .remove = rsnd_scu_remove_gen2, .init = rsnd_scu_init_gen2, .quit = rsnd_scu_quit, .start = rsnd_scu_start_gen2, @@ -631,25 +669,8 @@ int rsnd_scu_probe(struct platform_device *pdev, if (rsnd_scu_hpbif_is_enable(scu)) { if (rsnd_is_gen1(priv)) ops = &rsnd_scu_gen1_ops; - if (rsnd_is_gen2(priv)) { - int ret; - int is_play; - - if (info->dai_info) { - is_play = rsnd_info_is_playback(priv, scu); - } else { - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); - is_play = rsnd_ssi_is_play(ssi); - } - ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(&scu->mod), - is_play, - scu->info->dma_id); - if (ret < 0) - return ret; - + if (rsnd_is_gen2(priv)) ops = &rsnd_scu_gen2_ops; - } } rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); @@ -663,11 +684,4 @@ int rsnd_scu_probe(struct platform_device *pdev, void rsnd_scu_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_scu *scu; - int i; - - for_each_rsnd_scu(scu, priv, i) { - if (rsnd_scu_dma_available(scu)) - rsnd_dma_quit(priv, rsnd_mod_to_dma(&scu->mod)); - } } -- cgit v1.2.3-55-g7522 From ff8f30e688477beead6d1e648fb11f321220a4d7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:50:49 -0800 Subject: ASoC: rsnd: use mod probe method on SSI Now, it can use .probe Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 116 +++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 51 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index a7df216a46da..0f3eeac56155 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -358,6 +358,26 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) return ret; } +static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + int irq = ssi->info->pio_irq; + int ret; + + ret = devm_request_irq(dev, irq, + rsnd_ssi_pio_interrupt, + IRQF_SHARED, + dev_name(dev), ssi); + if (ret) + dev_err(dev, "SSI request interrupt failed\n"); + + return ret; +} + static int rsnd_ssi_pio_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -389,12 +409,50 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .name = "ssi (pio)", + .probe = rsnd_ssi_pio_probe, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_pio_start, .stop = rsnd_ssi_pio_stop, }; +static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int dma_id = ssi->info->dma_id; + int is_play; + int ret; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, ssi); + else + is_play = rsnd_ssi_is_play(&ssi->mod); + + ret = rsnd_dma_init( + priv, rsnd_mod_to_dma(mod), + is_play, + dma_id); + + if (ret < 0) + dev_err(dev, "SSI DMA failed\n"); + + return ret; +} + +static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + static int rsnd_ssi_dma_start(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -436,6 +494,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .name = "ssi (dma)", + .probe = rsnd_ssi_dma_probe, + .remove = rsnd_ssi_dma_remove, .init = rsnd_ssi_init, .quit = rsnd_ssi_quit, .start = rsnd_ssi_dma_start, @@ -538,7 +598,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct clk *clk; struct rsnd_ssi *ssi; char name[RSND_SSI_NAME_SIZE]; - int i, nr, ret; + int i, nr; /* * init SSI @@ -566,48 +626,10 @@ int rsnd_ssi_probe(struct platform_device *pdev, ssi->clk = clk; ops = &rsnd_ssi_non_ops; - - /* - * SSI DMA case - */ - if (pinfo->dma_id > 0) { - int is_play; - - if (info->dai_info) - is_play = rsnd_info_is_playback(priv, ssi); - else - is_play = rsnd_ssi_is_play(&ssi->mod); - - ret = rsnd_dma_init( - priv, rsnd_mod_to_dma(&ssi->mod), - is_play, - pinfo->dma_id); - if (ret < 0) - dev_info(dev, "SSI DMA failed. try PIO transter\n"); - else - ops = &rsnd_ssi_dma_ops; - - dev_dbg(dev, "SSI%d use DMA transfer\n", i); - } - - /* - * SSI PIO case - */ - if (!rsnd_ssi_dma_available(ssi) && - rsnd_ssi_pio_available(ssi)) { - ret = devm_request_irq(dev, pinfo->pio_irq, - &rsnd_ssi_pio_interrupt, - IRQF_SHARED, - dev_name(dev), ssi); - if (ret) { - dev_err(dev, "SSI request interrupt failed\n"); - return ret; - } - - ops = &rsnd_ssi_pio_ops; - - dev_dbg(dev, "SSI%d use PIO transfer\n", i); - } + if (pinfo->dma_id > 0) + ops = &rsnd_ssi_dma_ops; + else if (rsnd_ssi_pio_available(ssi)) + ops = &rsnd_ssi_pio_ops; rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i); @@ -620,12 +642,4 @@ int rsnd_ssi_probe(struct platform_device *pdev, void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_ssi *ssi; - int i; - - for_each_rsnd_ssi(ssi, priv, i) { - if (rsnd_ssi_dma_available(ssi)) - rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); - } - } -- cgit v1.2.3-55-g7522 From 4076220767416b8b65009dd57eeb317c38d41baa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:03 -0800 Subject: ASoC: rsnd: nothing to do on rsnd_dai_remove() rsnd_dai_remove() called rsnd_path_exit(), but these memory will be cleaned automatically. Because it is created by devm_kzalloc(). nothing to do on rsnd_dai_remove() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index e8e585de7251..92e155b7b6a7 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -348,14 +348,6 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, return 0; } -static int rsnd_dai_disconnect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) -{ - io->mod[mod->type] = NULL; - mod->io = NULL; - - return 0; -} - int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) { int id = rdai - priv->rdai; @@ -628,26 +620,6 @@ static int rsnd_path_init(struct rsnd_priv *priv, return ret; } -static int rsnd_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_mod *mod; - int ret = 0, i; - - /* - * remove all mod from rdai - */ - for (i = 0; i < RSND_MOD_MAX; i++) { - mod = io->mod[i]; - if (!mod) - continue; - ret |= rsnd_dai_disconnect(mod, io); - } - - return ret; -} - static int rsnd_dai_probe(struct platform_device *pdev, struct rsnd_priv *priv) { @@ -739,14 +711,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, static void rsnd_dai_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_dai *rdai; - int i; - - for (i = 0; i < rsnd_rdai_nr(priv); i++) { - rdai = rsnd_dai_get(priv, i); - rsnd_path_exit(priv, rdai, &rdai->playback); - rsnd_path_exit(priv, rdai, &rdai->capture); - } } /* -- cgit v1.2.3-55-g7522 From 9524be0e761edd9f3c020344677d914ed249d010 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:11 -0800 Subject: ASoC: rsnd: remove all rsnd_xxx_remove() Now, rsnd_xxx_remove() do nothing. remove these Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 5 ----- sound/soc/sh/rcar/core.c | 14 -------------- sound/soc/sh/rcar/gen.c | 5 ----- sound/soc/sh/rcar/rsnd.h | 8 -------- sound/soc/sh/rcar/scu.c | 5 ----- sound/soc/sh/rcar/ssi.c | 5 ----- 6 files changed, 42 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 8df00ac3b120..953f1cce982d 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -454,8 +454,3 @@ int rsnd_adg_probe(struct platform_device *pdev, return 0; } - -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 92e155b7b6a7..ceb4e8bd4970 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -708,11 +708,6 @@ static int rsnd_dai_probe(struct platform_device *pdev, return 0; } -static void rsnd_dai_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} - /* * pcm ops */ @@ -902,15 +897,6 @@ static int rsnd_remove(struct platform_device *pdev) return ret; } - /* - * remove each module - */ - rsnd_ssi_remove(pdev, priv); - rsnd_adg_remove(pdev, priv); - rsnd_scu_remove(pdev, priv); - rsnd_dai_remove(pdev, priv); - rsnd_gen_remove(pdev, priv); - return 0; } diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 92d1bc9acef0..9094970dbdfb 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -385,8 +385,3 @@ int rsnd_gen_probe(struct platform_device *pdev, return ret; } - -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index db20b3721953..878dc6e20ff2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -261,8 +261,6 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); */ int rsnd_gen_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_gen_remove(struct platform_device *pdev, - struct rsnd_priv *priv); void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); @@ -276,8 +274,6 @@ int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); int rsnd_adg_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_adg_remove(struct platform_device *pdev, - struct rsnd_priv *priv); int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, unsigned int src_rate, @@ -353,8 +349,6 @@ struct rsnd_priv { */ int rsnd_scu_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, @@ -373,8 +367,6 @@ int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, */ int rsnd_ssi_probe(struct platform_device *pdev, struct rsnd_priv *priv); -void rsnd_ssi_remove(struct platform_device *pdev, - struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, int dai_id, int is_play); diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 40250acf608d..3526a5c2f608 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -680,8 +680,3 @@ int rsnd_scu_probe(struct platform_device *pdev, return 0; } - -void rsnd_scu_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0f3eeac56155..45f828ded935 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -638,8 +638,3 @@ int rsnd_ssi_probe(struct platform_device *pdev, return 0; } - -void rsnd_ssi_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} -- cgit v1.2.3-55-g7522 From ba9c949f797aa3af56303445812a452144c61c35 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Mar 2014 20:51:21 -0800 Subject: ASoC: rsnd: rename scu to src R-Car sound has SCU unit which has SRC/CTU/MIX/DVC, and current rsnd driver has scu.c and scu module. Current scu.c has SRC support only. My first concept was control these feature on scu.c but, it become difficult and un-understandable now. This patch rename scu to src Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- include/sound/rcar_snd.h | 18 +- sound/soc/sh/rcar/Makefile | 2 +- sound/soc/sh/rcar/core.c | 26 +- sound/soc/sh/rcar/rsnd.h | 24 +- sound/soc/sh/rcar/scu.c | 682 -------------------------------------------- sound/soc/sh/rcar/src.c | 687 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/ssi.c | 6 +- 7 files changed, 727 insertions(+), 718 deletions(-) delete mode 100644 sound/soc/sh/rcar/scu.c create mode 100644 sound/soc/sh/rcar/src.c (limited to 'sound') diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 1d8c68323f49..34a3c02a4576 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -55,14 +55,18 @@ struct rsnd_ssi_platform_info { */ #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ -#define RSND_SCU(rate, _dma_id) \ +#define RSND_SRC(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } -#define RSND_SCU_SET(rate, _dma_id) \ +#define RSND_SRC_SET(rate, _dma_id) \ { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } -#define RSND_SCU_UNUSED \ +#define RSND_SRC_UNUSED \ { .flags = 0, .convert_rate = 0, .dma_id = 0, } -struct rsnd_scu_platform_info { +#define rsnd_scu_platform_info rsnd_src_platform_info +#define src_info scu_info +#define src_info_nr scu_info_nr + +struct rsnd_src_platform_info { u32 flags; u32 convert_rate; /* sampling rate convert */ int dma_id; /* for Gen2 SCU */ @@ -70,7 +74,7 @@ struct rsnd_scu_platform_info { struct rsnd_dai_path_info { struct rsnd_ssi_platform_info *ssi; - struct rsnd_scu_platform_info *scu; + struct rsnd_src_platform_info *src; }; struct rsnd_dai_platform_info { @@ -93,8 +97,8 @@ struct rcar_snd_info { u32 flags; struct rsnd_ssi_platform_info *ssi_info; int ssi_info_nr; - struct rsnd_scu_platform_info *scu_info; - int scu_info_nr; + struct rsnd_src_platform_info *src_info; + int src_info_nr; struct rsnd_dai_platform_info *dai_info; int dai_info_nr; int (*start)(int id); diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 0ff492df7929..7d0051ced838 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,2 +1,2 @@ -snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o +snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ceb4e8bd4970..6a1b45df8101 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -73,13 +73,13 @@ * | +- ssi[2] * | ... * | - * | ** these control scu + * | ** these control src * | - * +- scu + * +- src * | - * +- scu[0] - * +- scu[1] - * +- scu[2] + * +- src[0] + * +- src[1] + * +- src[2] * ... * * @@ -572,7 +572,7 @@ static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai_platform_info *dai_info = rdai->info; int ret; int ssi_id = -1; - int scu_id = -1; + int src_id = -1; /* * Gen1 is created by SRU/SSI, and this SRU is base module of @@ -587,8 +587,8 @@ static int rsnd_path_init(struct rsnd_priv *priv, if (dai_info) { if (rsnd_is_enable_path(io, ssi)) ssi_id = rsnd_info_id(priv, io, ssi); - if (rsnd_is_enable_path(io, scu)) - scu_id = rsnd_info_id(priv, io, scu); + if (rsnd_is_enable_path(io, src)) + src_id = rsnd_info_id(priv, io, src); } else { /* get SSI's ID */ mod = rsnd_ssi_mod_get_frm_dai(priv, @@ -596,14 +596,14 @@ static int rsnd_path_init(struct rsnd_priv *priv, rsnd_dai_is_play(rdai, io)); if (!mod) return 0; - ssi_id = scu_id = rsnd_mod_id(mod); + ssi_id = src_id = rsnd_mod_id(mod); } ret = 0; - /* SCU */ - if (scu_id >= 0) { - mod = rsnd_scu_mod_get(priv, scu_id); + /* SRC */ + if (src_id >= 0) { + mod = rsnd_src_mod_get(priv, src_id); ret = rsnd_dai_connect(mod, io); if (ret < 0) return ret; @@ -806,7 +806,7 @@ static int rsnd_probe(struct platform_device *pdev) struct rsnd_priv *priv) = { rsnd_gen_probe, rsnd_ssi_probe, - rsnd_scu_probe, + rsnd_src_probe, rsnd_adg_probe, rsnd_dai_probe, }; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 878dc6e20ff2..c46e0afa54ae 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -160,7 +160,7 @@ void rsnd_dma_quit(struct rsnd_priv *priv, * R-Car sound mod */ enum rsnd_mod_type { - RSND_MOD_SCU = 0, + RSND_MOD_SRC = 0, RSND_MOD_SSI, RSND_MOD_MAX, }; @@ -224,7 +224,7 @@ struct rsnd_dai_stream { int next_period_byte; }; #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) -#define rsnd_io_to_mod_scu(io) ((io)->mod[RSND_MOD_SCU]) +#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -302,10 +302,10 @@ struct rsnd_priv { void *gen; /* - * below value will be filled on rsnd_scu_probe() + * below value will be filled on rsnd_src_probe() */ - void *scu; - int scu_nr; + void *src; + int src_nr; /* * below value will be filled on rsnd_adg_probe() @@ -345,22 +345,22 @@ struct rsnd_priv { }) /* - * R-Car SCU + * R-Car SRC */ -int rsnd_scu_probe(struct platform_device *pdev, +int rsnd_src_probe(struct platform_device *pdev, struct rsnd_priv *priv); -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); -int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); -#define rsnd_scu_nr(priv) ((priv)->scu_nr) +#define rsnd_src_nr(priv) ((priv)->src_nr) /* * R-Car SSI diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c deleted file mode 100644 index 3526a5c2f608..000000000000 --- a/sound/soc/sh/rcar/scu.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Renesas R-Car SCU support - * - * Copyright (C) 2013 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_scu { - struct rsnd_scu_platform_info *info; /* rcar_snd.h */ - struct rsnd_mod mod; - struct clk *clk; -}; - -#define RSND_SCU_NAME_SIZE 16 - -/* - * ADINR - */ -#define OTBL_24 (0 << 16) -#define OTBL_22 (2 << 16) -#define OTBL_20 (4 << 16) -#define OTBL_18 (6 << 16) -#define OTBL_16 (8 << 16) - -#define rsnd_scu_mode_flags(p) ((p)->info->flags) -#define rsnd_scu_convert_rate(p) ((p)->info->convert_rate) -#define rsnd_mod_to_scu(_mod) \ - container_of((_mod), struct rsnd_scu, mod) -#define rsnd_scu_hpbif_is_enable(scu) \ - (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) -#define rsnd_scu_dma_available(scu) \ - rsnd_dma_available(rsnd_mod_to_dma(&(scu)->mod)) - -#define for_each_rsnd_scu(pos, priv, i) \ - for ((i) = 0; \ - ((i) < rsnd_scu_nr(priv)) && \ - ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ - i++) - - -/* - * image of SRC (Sampling Rate Converter) - * - * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ - * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | - * 44.1kHz <-> +-----+ +-----+ +-------+ - * ... - * - */ - -/* - * scu.c is caring... - * - * Gen1 - * - * [mem] -> [SRU] -> [SSI] - * |--------| - * - * Gen2 - * - * [mem] -> [SCU] -> [SSIU] -> [SSI] - * |-----------------| - */ - -/* - * How to use SRC bypass mode for debugging - * - * SRC has bypass mode, and it is useful for debugging. - * In Gen2 case, - * SRCm_MODE controls whether SRC is used or not - * SSI_MODE0 controls whether SSIU which receives SRC data - * is used or not. - * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, - * but SRC bypass mode needs SSI_MODE0 only. - * - * This driver request - * struct rsnd_scu_platform_info { - * u32 flags; - * u32 convert_rate; - * } - * - * rsnd_scu_hpbif_is_enable() will be true - * if flags had RSND_SCU_USE_HPBIF, - * and it controls whether SSIU is used or not. - * - * rsnd_scu_convert_rate() indicates - * above convert_rate, and it controls - * whether SRC is used or not. - * - * ex) doesn't use SRC - * struct rsnd_scu_platform_info info = { - * .flags = 0, - * .convert_rate = 0, - * }; - * - * ex) uses SRC - * struct rsnd_scu_platform_info info = { - * .flags = RSND_SCU_USE_HPBIF, - * .convert_rate = 48000, - * }; - * - * ex) uses SRC bypass mode - * struct rsnd_scu_platform_info info = { - * .flags = RSND_SCU_USE_HPBIF, - * .convert_rate = 0, - * }; - * - */ - -/* - * Gen1/Gen2 common functions - */ -int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); - struct rsnd_mod *scu_mod = rsnd_io_to_mod_scu(io); - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - int ssi_id = rsnd_mod_id(ssi_mod); - int has_scu = 0; - - /* - * SSI_MODE0 - */ - if (info->dai_info) { - has_scu = !!scu_mod; - } else { - struct rsnd_scu *scu = rsnd_mod_to_scu(scu_mod); - has_scu = rsnd_scu_hpbif_is_enable(scu); - } - - rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), - has_scu ? 0 : (1 << ssi_id)); - - /* - * SSI_MODE1 - */ - if (rsnd_ssi_is_pin_sharing(ssi_mod)) { - int shift = -1; - switch (ssi_id) { - case 1: - shift = 0; - break; - case 2: - shift = 2; - break; - case 4: - shift = 16; - break; - } - - if (shift >= 0) - rsnd_mod_bset(ssi_mod, SSI_MODE1, - 0x3 << shift, - rsnd_dai_is_clk_master(rdai) ? - 0x2 << shift : 0x1 << shift); - } - - return 0; -} - -int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); - - /* enable PIO interrupt if Gen2 */ - if (rsnd_is_gen2(priv)) - rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); - - return 0; -} - -unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv, - struct rsnd_dai_stream *io, - struct snd_pcm_runtime *runtime) -{ - struct rsnd_scu *scu; - unsigned int rate; - - scu = rsnd_mod_to_scu(rsnd_io_to_mod_scu(io)); - - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_scu_convert_rate(scu); - if (!rate) - rate = runtime->rate; - - return rate; -} - -static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 adinr = runtime->channels; - u32 fsrate = 0; - - if (convert_rate) - fsrate = 0x0400000 / convert_rate * runtime->rate; - - /* set/clear soft reset */ - rsnd_mod_write(mod, SRC_SWRSR, 0); - rsnd_mod_write(mod, SRC_SWRSR, 1); - - /* - * Initialize the operation of the SRC internal circuits - * see rsnd_scu_start() - */ - rsnd_mod_write(mod, SRC_SRCIR, 1); - - /* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); - - /* Enable the initial value of IFS */ - if (fsrate) { - rsnd_mod_write(mod, SRC_IFSCR, 1); - - /* Set initial value of IFS */ - rsnd_mod_write(mod, SRC_IFSVR, fsrate); - } - - /* use DMA transfer */ - rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); - - return 0; -} - -static int rsnd_scu_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - clk_enable(scu->clk); - - return 0; -} - -static int rsnd_scu_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - clk_disable(scu->clk); - - return 0; -} - -static int rsnd_scu_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - /* - * Cancel the initialization and operate the SRC function - * see rsnd_scu_set_convert_rate() - */ - rsnd_mod_write(mod, SRC_SRCIR, 0); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); - - return 0; -} - - -static int rsnd_scu_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - if (rsnd_scu_convert_rate(scu)) - rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); - - return 0; -} - -static struct rsnd_mod_ops rsnd_scu_non_ops = { - .name = "scu (non)", -}; - -/* - * Gen1 functions - */ -static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct scu_route_config { - u32 mask; - int shift; - } routes[] = { - { 0xF, 0, }, /* 0 */ - { 0xF, 4, }, /* 1 */ - { 0xF, 8, }, /* 2 */ - { 0x7, 12, }, /* 3 */ - { 0x7, 16, }, /* 4 */ - { 0x7, 20, }, /* 5 */ - { 0x7, 24, }, /* 6 */ - { 0x3, 28, }, /* 7 */ - { 0x3, 30, }, /* 8 */ - }; - u32 mask; - u32 val; - int id; - - id = rsnd_mod_id(mod); - if (id < 0 || id >= ARRAY_SIZE(routes)) - return -EIO; - - /* - * SRC_ROUTE_SELECT - */ - val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; - val = val << routes[id].shift; - mask = routes[id].mask << routes[id].shift; - - rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); - - return 0; -} - -static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - u32 convert_rate = rsnd_scu_convert_rate(scu); - u32 mask; - u32 val; - int shift; - int id = rsnd_mod_id(mod); - int ret; - - /* - * SRC_TIMING_SELECT - */ - shift = (id % 4) * 8; - mask = 0x1F << shift; - - /* - * ADG is used as source clock if SRC was used, - * then, SSI WS is used as destination clock. - * SSI WS is used as source clock if SRC is not used - * (when playback, source/destination become reverse when capture) - */ - ret = 0; - if (convert_rate) { - /* use ADG */ - val = 0; - ret = rsnd_adg_set_convert_clk_gen1(priv, mod, - runtime->rate, - convert_rate); - } else if (8 == id) { - /* use SSI WS, but SRU8 is special */ - val = id << shift; - } else { - /* use SSI WS */ - val = (id + 1) << shift; - } - - if (ret < 0) - return ret; - - switch (id / 4) { - case 0: - rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); - break; - case 1: - rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); - break; - case 2: - rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); - break; - } - - return 0; -} - -static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_set_convert_rate(mod, rdai, io); - if (ret < 0) - return ret; - - /* Select SRC mode (fixed value) */ - rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); - - /* Set the restriction value of the FS ratio (98%) */ - rsnd_mod_write(mod, SRC_MNFSR, - rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); - - /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ - - return 0; -} - -static int rsnd_scu_init_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_init(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_src_set_route_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_rate_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_timing_gen1(mod, rdai, io); - if (ret < 0) - return ret; - - return 0; -} - -static int rsnd_scu_start_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int id = rsnd_mod_id(mod); - - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); - - return rsnd_scu_start(mod, rdai, io); -} - -static int rsnd_scu_stop_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int id = rsnd_mod_id(mod); - - rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); - - return rsnd_scu_stop(mod, rdai, io); -} - -static struct rsnd_mod_ops rsnd_scu_gen1_ops = { - .name = "sru (gen1)", - .init = rsnd_scu_init_gen1, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start_gen1, - .stop = rsnd_scu_stop_gen1, -}; - -/* - * Gen2 functions - */ -static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_set_convert_rate(mod, rdai, io); - if (ret < 0) - return ret; - - rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); - rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); - - rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); - - rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); - rsnd_mod_write(mod, SRC_BSISR, 0x00100060); - - return 0; -} - -static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - u32 convert_rate = rsnd_scu_convert_rate(scu); - int ret; - - if (convert_rate) - ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, - runtime->rate, - convert_rate); - else - ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); - - return ret; -} - -static int rsnd_scu_probe_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); - struct device *dev = rsnd_priv_to_dev(priv); - int ret; - int is_play; - - if (info->dai_info) - is_play = rsnd_info_is_playback(priv, scu); - else - is_play = rsnd_ssi_is_play(ssi); - - ret = rsnd_dma_init(priv, - rsnd_mod_to_dma(mod), - is_play, - scu->info->dma_id); - if (ret < 0) - dev_err(dev, "SCU DMA failed\n"); - - return ret; -} - -static int rsnd_scu_remove_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); - - return 0; -} - -static int rsnd_scu_init_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - int ret; - - ret = rsnd_scu_init(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_rate_gen2(mod, rdai, io); - if (ret < 0) - return ret; - - ret = rsnd_scu_set_convert_timing_gen2(mod, rdai, io); - if (ret < 0) - return ret; - - return 0; -} - -static int rsnd_scu_start_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - rsnd_dma_start(rsnd_mod_to_dma(&scu->mod)); - - rsnd_mod_write(mod, SSI_CTRL, 0x1); - rsnd_mod_write(mod, SRC_CTRL, 0x11); - - return rsnd_scu_start(mod, rdai, io); -} - -static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_scu *scu = rsnd_mod_to_scu(mod); - - rsnd_mod_write(mod, SSI_CTRL, 0); - rsnd_mod_write(mod, SRC_CTRL, 0); - - rsnd_dma_stop(rsnd_mod_to_dma(&scu->mod)); - - return rsnd_scu_stop(mod, rdai, io); -} - -static struct rsnd_mod_ops rsnd_scu_gen2_ops = { - .name = "scu (gen2)", - .probe = rsnd_scu_probe_gen2, - .remove = rsnd_scu_remove_gen2, - .init = rsnd_scu_init_gen2, - .quit = rsnd_scu_quit, - .start = rsnd_scu_start_gen2, - .stop = rsnd_scu_stop_gen2, -}; - -struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) -{ - if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv))) - id = 0; - - return &((struct rsnd_scu *)(priv->scu) + id)->mod; -} - -int rsnd_scu_probe(struct platform_device *pdev, - struct rsnd_priv *priv) -{ - struct rcar_snd_info *info = rsnd_priv_to_info(priv); - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_scu *scu; - struct rsnd_mod_ops *ops; - struct clk *clk; - char name[RSND_SCU_NAME_SIZE]; - int i, nr; - - /* - * init SCU - */ - nr = info->scu_info_nr; - if (!nr) - return 0; - - scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); - if (!scu) { - dev_err(dev, "SCU allocate failed\n"); - return -ENOMEM; - } - - priv->scu_nr = nr; - priv->scu = scu; - - for_each_rsnd_scu(scu, priv, i) { - snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i); - - clk = devm_clk_get(dev, name); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - scu->info = &info->scu_info[i]; - scu->clk = clk; - - ops = &rsnd_scu_non_ops; - if (rsnd_scu_hpbif_is_enable(scu)) { - if (rsnd_is_gen1(priv)) - ops = &rsnd_scu_gen1_ops; - if (rsnd_is_gen2(priv)) - ops = &rsnd_scu_gen2_ops; - } - - rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i); - - dev_dbg(dev, "SCU%d probed\n", i); - } - - return 0; -} diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c new file mode 100644 index 000000000000..ea6a214985d0 --- /dev/null +++ b/sound/soc/sh/rcar/src.c @@ -0,0 +1,687 @@ +/* + * Renesas R-Car SRC support + * + * Copyright (C) 2013 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_src { + struct rsnd_src_platform_info *info; /* rcar_snd.h */ + struct rsnd_mod mod; + struct clk *clk; +}; + +#define RSND_SRC_NAME_SIZE 16 + +/* + * ADINR + */ +#define OTBL_24 (0 << 16) +#define OTBL_22 (2 << 16) +#define OTBL_20 (4 << 16) +#define OTBL_18 (6 << 16) +#define OTBL_16 (8 << 16) + +#define rsnd_src_mode_flags(p) ((p)->info->flags) +#define rsnd_src_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_mod_to_src(_mod) \ + container_of((_mod), struct rsnd_src, mod) +#define rsnd_src_hpbif_is_enable(src) \ + (rsnd_src_mode_flags(src) & RSND_SCU_USE_HPBIF) +#define rsnd_src_dma_available(src) \ + rsnd_dma_available(rsnd_mod_to_dma(&(src)->mod)) + +#define for_each_rsnd_src(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_src_nr(priv)) && \ + ((pos) = (struct rsnd_src *)(priv)->src + i); \ + i++) + + +/* + * image of SRC (Sampling Rate Converter) + * + * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ + * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | + * 44.1kHz <-> +-----+ +-----+ +-------+ + * ... + * + */ + +/* + * src.c is caring... + * + * Gen1 + * + * [mem] -> [SRU] -> [SSI] + * |--------| + * + * Gen2 + * + * [mem] -> [SRC] -> [SSIU] -> [SSI] + * |-----------------| + */ + +/* + * How to use SRC bypass mode for debugging + * + * SRC has bypass mode, and it is useful for debugging. + * In Gen2 case, + * SRCm_MODE controls whether SRC is used or not + * SSI_MODE0 controls whether SSIU which receives SRC data + * is used or not. + * Both SRCm_MODE/SSI_MODE0 settings are needed if you use SRC, + * but SRC bypass mode needs SSI_MODE0 only. + * + * This driver request + * struct rsnd_src_platform_info { + * u32 flags; + * u32 convert_rate; + * } + * + * rsnd_src_hpbif_is_enable() will be true + * if flags had RSND_SRC_USE_HPBIF, + * and it controls whether SSIU is used or not. + * + * rsnd_src_convert_rate() indicates + * above convert_rate, and it controls + * whether SRC is used or not. + * + * ex) doesn't use SRC + * struct rsnd_src_platform_info info = { + * .flags = 0, + * .convert_rate = 0, + * }; + * + * ex) uses SRC + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 48000, + * }; + * + * ex) uses SRC bypass mode + * struct rsnd_src_platform_info info = { + * .flags = RSND_SRC_USE_HPBIF, + * .convert_rate = 0, + * }; + * + */ + +/* + * Gen1/Gen2 common functions + */ +int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + int ssi_id = rsnd_mod_id(ssi_mod); + int has_src = 0; + + /* + * SSI_MODE0 + */ + if (info->dai_info) { + has_src = !!src_mod; + } else { + struct rsnd_src *src = rsnd_mod_to_src(src_mod); + has_src = rsnd_src_hpbif_is_enable(src); + } + + rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), + has_src ? 0 : (1 << ssi_id)); + + /* + * SSI_MODE1 + */ + if (rsnd_ssi_is_pin_sharing(ssi_mod)) { + int shift = -1; + switch (ssi_id) { + case 1: + shift = 0; + break; + case 2: + shift = 2; + break; + case 4: + shift = 16; + break; + } + + if (shift >= 0) + rsnd_mod_bset(ssi_mod, SSI_MODE1, + 0x3 << shift, + rsnd_dai_is_clk_master(rdai) ? + 0x2 << shift : 0x1 << shift); + } + + return 0; +} + +int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + + /* enable PIO interrupt if Gen2 */ + if (rsnd_is_gen2(priv)) + rsnd_mod_write(ssi_mod, INT_ENABLE, 0x0f000000); + + return 0; +} + +unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, + struct rsnd_dai_stream *io, + struct snd_pcm_runtime *runtime) +{ + struct rsnd_src *src; + unsigned int rate; + + src = rsnd_mod_to_src(rsnd_io_to_mod_src(io)); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_src_convert_rate(src); + if (!rate) + rate = runtime->rate; + + return rate; +} + +static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 adinr = runtime->channels; + u32 fsrate = 0; + + if (convert_rate) + fsrate = 0x0400000 / convert_rate * runtime->rate; + + /* set/clear soft reset */ + rsnd_mod_write(mod, SRC_SWRSR, 0); + rsnd_mod_write(mod, SRC_SWRSR, 1); + + /* + * Initialize the operation of the SRC internal circuits + * see rsnd_src_start() + */ + rsnd_mod_write(mod, SRC_SRCIR, 1); + + /* Set channel number and output bit length */ + switch (runtime->sample_bits) { + case 16: + adinr |= OTBL_16; + break; + case 32: + adinr |= OTBL_24; + break; + default: + return -EIO; + } + rsnd_mod_write(mod, SRC_ADINR, adinr); + + /* Enable the initial value of IFS */ + if (fsrate) { + rsnd_mod_write(mod, SRC_IFSCR, 1); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + } + + /* use DMA transfer */ + rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); + + return 0; +} + +static int rsnd_src_init(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_enable(src->clk); + + return 0; +} + +static int rsnd_src_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + clk_disable(src->clk); + + return 0; +} + +static int rsnd_src_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + /* + * Cancel the initialization and operate the SRC function + * see rsnd_src_set_convert_rate() + */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1); + + return 0; +} + + +static int rsnd_src_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + if (rsnd_src_convert_rate(src)) + rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0); + + return 0; +} + +static struct rsnd_mod_ops rsnd_src_non_ops = { + .name = "src (non)", +}; + +/* + * Gen1 functions + */ +static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct src_route_config { + u32 mask; + int shift; + } routes[] = { + { 0xF, 0, }, /* 0 */ + { 0xF, 4, }, /* 1 */ + { 0xF, 8, }, /* 2 */ + { 0x7, 12, }, /* 3 */ + { 0x7, 16, }, /* 4 */ + { 0x7, 20, }, /* 5 */ + { 0x7, 24, }, /* 6 */ + { 0x3, 28, }, /* 7 */ + { 0x3, 30, }, /* 8 */ + }; + u32 mask; + u32 val; + int id; + + id = rsnd_mod_id(mod); + if (id < 0 || id >= ARRAY_SIZE(routes)) + return -EIO; + + /* + * SRC_ROUTE_SELECT + */ + val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; + val = val << routes[id].shift; + mask = routes[id].mask << routes[id].shift; + + rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + u32 convert_rate = rsnd_src_convert_rate(src); + u32 mask; + u32 val; + int shift; + int id = rsnd_mod_id(mod); + int ret; + + /* + * SRC_TIMING_SELECT + */ + shift = (id % 4) * 8; + mask = 0x1F << shift; + + /* + * ADG is used as source clock if SRC was used, + * then, SSI WS is used as destination clock. + * SSI WS is used as source clock if SRC is not used + * (when playback, source/destination become reverse when capture) + */ + ret = 0; + if (convert_rate) { + /* use ADG */ + val = 0; + ret = rsnd_adg_set_convert_clk_gen1(priv, mod, + runtime->rate, + convert_rate); + } else if (8 == id) { + /* use SSI WS, but SRU8 is special */ + val = id << shift; + } else { + /* use SSI WS */ + val = (id + 1) << shift; + } + + if (ret < 0) + return ret; + + switch (id / 4) { + case 0: + rsnd_mod_bset(mod, SRC_TMG_SEL0, mask, val); + break; + case 1: + rsnd_mod_bset(mod, SRC_TMG_SEL1, mask, val); + break; + case 2: + rsnd_mod_bset(mod, SRC_TMG_SEL2, mask, val); + break; + } + + return 0; +} + +static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + /* Select SRC mode (fixed value) */ + rsnd_mod_write(mod, SRC_SRCCR, 0x00010110); + + /* Set the restriction value of the FS ratio (98%) */ + rsnd_mod_write(mod, SRC_MNFSR, + rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98); + + /* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ + + return 0; +} + +static int rsnd_src_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_route_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen1(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id)); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen1_ops = { + .name = "sru (gen1)", + .init = rsnd_src_init_gen1, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen1, + .stop = rsnd_src_stop_gen1, +}; + +/* + * Gen2 functions + */ +static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_set_convert_rate(mod, rdai, io); + if (ret < 0) + return ret; + + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + + rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); + + rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); + rsnd_mod_write(mod, SRC_BSISR, 0x00100060); + + return 0; +} + +static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 convert_rate = rsnd_src_convert_rate(src); + int ret; + + if (convert_rate) + ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, + runtime->rate, + convert_rate); + else + ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); + + return ret; +} + +static int rsnd_src_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct rsnd_src *src = rsnd_mod_to_src(mod); + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, rsnd_mod_id(mod)); + struct device *dev = rsnd_priv_to_dev(priv); + int ret; + int is_play; + + if (info->dai_info) + is_play = rsnd_info_is_playback(priv, src); + else + is_play = rsnd_ssi_is_play(ssi); + + ret = rsnd_dma_init(priv, + rsnd_mod_to_dma(mod), + is_play, + src->info->dma_id); + if (ret < 0) + dev_err(dev, "SRC DMA failed\n"); + + return ret; +} + +static int rsnd_src_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); + + return 0; +} + +static int rsnd_src_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + int ret; + + ret = rsnd_src_init(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_rate_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + ret = rsnd_src_set_convert_timing_gen2(mod, rdai, io); + if (ret < 0) + return ret; + + return 0; +} + +static int rsnd_src_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); + + rsnd_mod_write(mod, SSI_CTRL, 0x1); + rsnd_mod_write(mod, SRC_CTRL, 0x11); + + return rsnd_src_start(mod, rdai, io); +} + +static int rsnd_src_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) +{ + struct rsnd_src *src = rsnd_mod_to_src(mod); + + rsnd_mod_write(mod, SSI_CTRL, 0); + rsnd_mod_write(mod, SRC_CTRL, 0); + + rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); + + return rsnd_src_stop(mod, rdai, io); +} + +static struct rsnd_mod_ops rsnd_src_gen2_ops = { + .name = "src (gen2)", + .probe = rsnd_src_probe_gen2, + .remove = rsnd_src_remove_gen2, + .init = rsnd_src_init_gen2, + .quit = rsnd_src_quit, + .start = rsnd_src_start_gen2, + .stop = rsnd_src_stop_gen2, +}; + +struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id) +{ + if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv))) + id = 0; + + return &((struct rsnd_src *)(priv->src) + id)->mod; +} + +int rsnd_src_probe(struct platform_device *pdev, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_src *src; + struct rsnd_mod_ops *ops; + struct clk *clk; + char name[RSND_SRC_NAME_SIZE]; + int i, nr; + + /* + * init SRC + */ + nr = info->src_info_nr; + if (!nr) + return 0; + + src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL); + if (!src) { + dev_err(dev, "SRC allocate failed\n"); + return -ENOMEM; + } + + priv->src_nr = nr; + priv->src = src; + + for_each_rsnd_src(src, priv, i) { + snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i); + + clk = devm_clk_get(dev, name); + if (IS_ERR(clk)) { + snprintf(name, RSND_SRC_NAME_SIZE, "scu.%d", i); + clk = devm_clk_get(dev, name); + } + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + src->info = &info->src_info[i]; + src->clk = clk; + + ops = &rsnd_src_non_ops; + if (rsnd_src_hpbif_is_enable(src)) { + if (rsnd_is_gen1(priv)) + ops = &rsnd_src_gen1_ops; + if (rsnd_is_gen2(priv)) + ops = &rsnd_src_gen2_ops; + } + + rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i); + + dev_dbg(dev, "SRC%d probed\n", i); + } + + return 0; +} diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 45f828ded935..633b23d209b9 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -121,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; - unsigned int rate = rsnd_scu_get_ssi_rate(priv, io, runtime); + unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG @@ -287,7 +287,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */ - rsnd_scu_ssi_mode_init(mod, rdai, io); + rsnd_src_ssi_mode_init(mod, rdai, io); return 0; } @@ -387,7 +387,7 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - rsnd_scu_enable_ssi_irq(mod, rdai, io); + rsnd_src_enable_ssi_irq(mod, rdai, io); rsnd_ssi_hw_start(ssi, rdai, io); -- cgit v1.2.3-55-g7522