From a37377314ff068c83f425979142263a17a6f18af Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Nov 2013 12:46:53 +0300 Subject: ASoC: rcar: some dubious one-bit signed bitfields Because these are signed they can either be 0 or -1 instead of 0 and 1 as intended. It doesn't cause a problem from what I can see, but it's dangerous and Sparse complains: sound/soc/sh/rcar/rsnd.h:177:25: error: dubious one-bit signed bitfield Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9e463e50e7e6..b5ac3a2afc58 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -174,11 +174,11 @@ struct rsnd_dai { struct rsnd_dai_stream playback; struct rsnd_dai_stream capture; - int clk_master:1; - int bit_clk_inv:1; - int frm_clk_inv:1; - int sys_delay:1; - int data_alignment:1; + unsigned int clk_master:1; + unsigned int bit_clk_inv:1; + unsigned int frm_clk_inv:1; + unsigned int sys_delay:1; + unsigned int data_alignment:1; }; #define rsnd_dai_nr(priv) ((priv)->dai_nr) -- cgit v1.2.1 From 17b9a2b78586c42916a2bfc55ea6c0ef962b2c1e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 18:42:49 -0800 Subject: ASoC: rcar: remove unused register settings AUDIO_CLK_SEL4/5 are not used Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 3 --- sound/soc/sh/rcar/rsnd.h | 3 --- 2 files changed, 6 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 61212ee97c28..b94d4cefa8b8 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -208,9 +208,6 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), - RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), - RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), - RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b5ac3a2afc58..63a9d7081c60 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -49,9 +49,6 @@ enum rsnd_reg { RSND_REG_AUDIO_CLK_SEL0, RSND_REG_AUDIO_CLK_SEL1, RSND_REG_AUDIO_CLK_SEL2, - RSND_REG_AUDIO_CLK_SEL3, - RSND_REG_AUDIO_CLK_SEL4, - RSND_REG_AUDIO_CLK_SEL5, /* SSI */ RSND_REG_SSICR, -- cgit v1.2.1 From c1e6cc5e577d1d446a645aea02d28a924f20b834 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 18:43:01 -0800 Subject: ASoC: rcar: separate regmap init common field The repmap initialization difference between Gen1/Gen2 is only register offset. This patch separates rsnd_gen1_regmap_init() into common part and Gen1 specific part. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index b94d4cefa8b8..0ebea44e890f 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -115,6 +115,33 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, mask, data); } +static int rsnd_gen_regmap_init(struct rsnd_priv *priv, + struct rsnd_gen *gen, + struct reg_field *regf) +{ + int i; + struct device *dev = rsnd_priv_to_dev(priv); + struct regmap_config regc; + + memset(®c, 0, sizeof(regc)); + regc.reg_bits = 32; + regc.val_bits = 32; + + gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); + if (IS_ERR(gen->regmap)) { + dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); + return PTR_ERR(gen->regmap); + } + + for (i = 0; i < RSND_REG_MAX; i++) { + gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); + if (IS_ERR(gen->regs[i])) + return PTR_ERR(gen->regs[i]); + + } + + return 0; +} /* * Gen2 * will be filled in the future @@ -189,9 +216,6 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv, static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) { - int i; - struct device *dev = rsnd_priv_to_dev(priv); - struct regmap_config regc; struct reg_field regf[RSND_REG_MAX] = { RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00), RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), @@ -216,24 +240,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), }; - memset(®c, 0, sizeof(regc)); - regc.reg_bits = 32; - regc.val_bits = 32; - - gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, ®c); - if (IS_ERR(gen->regmap)) { - dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap)); - return PTR_ERR(gen->regmap); - } - - for (i = 0; i < RSND_REG_MAX; i++) { - gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); - if (IS_ERR(gen->regs[i])) - return PTR_ERR(gen->regs[i]); - - } - - return 0; + return rsnd_gen_regmap_init(priv, gen, regf); } static int rsnd_gen1_probe(struct platform_device *pdev, -- cgit v1.2.1 From 42ee5d22e3d2550a49bc5d3e6f19c92da9a19446 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 18:43:13 -0800 Subject: ASoC: rcar: add rsnd_is_accessible_reg() Current rcar driver is supporting Gen1, and Gen2 will be supported soon. Then, some registers are used from Gen1 only, or from Gen2 only. To avoid NULL pointer access, this patch adds register accessible check function. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 0ebea44e890f..970439d5ec0e 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -86,12 +86,28 @@ static struct regmap_bus rsnd_regmap_bus = { .val_format_endian_default = REGMAP_ENDIAN_NATIVE, }; +static int rsnd_is_accessible_reg(struct rsnd_priv *priv, + struct rsnd_gen *gen, enum rsnd_reg reg) +{ + if (!gen->regs[reg]) { + struct device *dev = rsnd_priv_to_dev(priv); + + dev_err(dev, "unsupported register access %x\n", reg); + return 0; + } + + return 1; +} + u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg) { struct rsnd_gen *gen = rsnd_priv_to_gen(priv); u32 val; + if (!rsnd_is_accessible_reg(priv, gen, reg)) + return 0; + regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); return val; @@ -103,6 +119,9 @@ void rsnd_write(struct rsnd_priv *priv, { struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + if (!rsnd_is_accessible_reg(priv, gen, reg)) + return; + regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); } @@ -111,6 +130,9 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, { struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + if (!rsnd_is_accessible_reg(priv, gen, reg)) + return; + regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), mask, data); } @@ -134,6 +156,10 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, } for (i = 0; i < RSND_REG_MAX; i++) { + gen->regs[i] = NULL; + if (!regf[i].reg) + continue; + gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]); if (IS_ERR(gen->regs[i])) return PTR_ERR(gen->regs[i]); -- cgit v1.2.1 From 994a9df1e3ea3244e94309e4f893e9a5121116c9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 18:43:23 -0800 Subject: ASoC: rcar: remove .path_init/exit from rsnd_gen_ops rsnd_gen_ops has .path_init/exit callback function which cares SRU/SSI (if Gen1) SCU/SSIU/SSI (if Gen2) path settings. But, the differences between Gen1/Gen2 are cared in ssi.c/scu.c, and the path itself is same in Gen1/Gen2. This patch removes .path_init/exit callback. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 54 ++++++++++++++----------------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 970439d5ec0e..4f2eaa3262d7 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -16,12 +16,6 @@ struct rsnd_gen_ops { struct rsnd_priv *priv); void (*remove)(struct platform_device *pdev, struct rsnd_priv *priv); - int (*path_init)(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); - int (*path_exit)(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); }; struct rsnd_gen { @@ -168,17 +162,10 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv, return 0; } -/* - * Gen2 - * will be filled in the future - */ -/* - * Gen1 - */ -static int rsnd_gen1_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) +int rsnd_gen_path_init(struct rsnd_priv *priv, + struct rsnd_dai *rdai, + struct rsnd_dai_stream *io) { struct rsnd_mod *mod; int ret; @@ -216,9 +203,9 @@ static int rsnd_gen1_path_init(struct rsnd_priv *priv, return ret; } -static int rsnd_gen1_path_exit(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) { struct rsnd_mod *mod, *n; int ret = 0; @@ -232,6 +219,15 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv, return ret; } +/* + * Gen2 + * will be filled in the future + */ + +/* + * Gen1 + */ + /* single address mapping */ #define RSND_GEN1_S_REG(gen, reg, id, offset) \ RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9) @@ -319,31 +315,11 @@ static void rsnd_gen1_remove(struct platform_device *pdev, static struct rsnd_gen_ops rsnd_gen1_ops = { .probe = rsnd_gen1_probe, .remove = rsnd_gen1_remove, - .path_init = rsnd_gen1_path_init, - .path_exit = rsnd_gen1_path_exit, }; /* * Gen */ -int rsnd_gen_path_init(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_gen *gen = rsnd_priv_to_gen(priv); - - return gen->ops->path_init(priv, rdai, io); -} - -int rsnd_gen_path_exit(struct rsnd_priv *priv, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - struct rsnd_gen *gen = rsnd_priv_to_gen(priv); - - return gen->ops->path_exit(priv, rdai, io); -} - int rsnd_gen_probe(struct platform_device *pdev, struct rcar_snd_info *info, struct rsnd_priv *priv) -- cgit v1.2.1 From 531eaf491e25ce215bbcf434e23e77f53fc98171 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 18:43:34 -0800 Subject: ASoC: rcar: remove rcar_gen_ops Current rcar driver gen.c is using rcar_gen_ops which was made with the assumption that Gen1 and Gen2 need different behavior. but it was not needed. This patch removes unnecessary complex method. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 4f2eaa3262d7..a29e36eb1a30 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -10,14 +10,6 @@ */ #include "rsnd.h" -struct rsnd_gen_ops { - int (*probe)(struct platform_device *pdev, - struct rcar_snd_info *info, - struct rsnd_priv *priv); - void (*remove)(struct platform_device *pdev, - struct rsnd_priv *priv); -}; - struct rsnd_gen { void __iomem *base[RSND_BASE_MAX]; @@ -307,16 +299,6 @@ static int rsnd_gen1_probe(struct platform_device *pdev, } -static void rsnd_gen1_remove(struct platform_device *pdev, - struct rsnd_priv *priv) -{ -} - -static struct rsnd_gen_ops rsnd_gen1_ops = { - .probe = rsnd_gen1_probe, - .remove = rsnd_gen1_remove, -}; - /* * Gen */ @@ -326,6 +308,7 @@ int rsnd_gen_probe(struct platform_device *pdev, { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_gen *gen; + int ret; gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); if (!gen) { @@ -333,23 +316,19 @@ int rsnd_gen_probe(struct platform_device *pdev, return -ENOMEM; } - if (rsnd_is_gen1(priv)) - gen->ops = &rsnd_gen1_ops; + priv->gen = gen; - if (!gen->ops) { + if (rsnd_is_gen1(priv)) { + ret = rsnd_gen1_probe(pdev, info, priv); + } else { dev_err(dev, "unknown generation R-Car sound device\n"); return -ENODEV; } - priv->gen = gen; - - return gen->ops->probe(pdev, info, priv); + return ret; } void rsnd_gen_remove(struct platform_device *pdev, struct rsnd_priv *priv) { - struct rsnd_gen *gen = rsnd_priv_to_gen(priv); - - gen->ops->remove(pdev, priv); } -- cgit v1.2.1 From 507d466c733e28d132a7be87040a3da126df7947 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 28 Nov 2013 18:43:45 -0800 Subject: ASoC: rcar: add Gen2 sound support This patch adds Gen2 sound support for Renesas R-Car. But, it is supporting PIO transfer only at this point Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 91 +++++++++++++++++++++++++++++++++++++++++++++--- sound/soc/sh/rcar/rsnd.h | 3 +- sound/soc/sh/rcar/ssi.c | 3 ++ 3 files changed, 91 insertions(+), 6 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index a29e36eb1a30..bf066f73ef05 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -213,9 +213,88 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv, /* * Gen2 - * will be filled in the future */ +/* single address mapping */ +#define RSND_GEN2_S_REG(gen, reg, id, offset) \ + RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 9) + +/* multi address mapping */ +#define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \ + RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 9) + +static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) +{ + struct reg_field regf[RSND_REG_MAX] = { + RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), + RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), + /* FIXME: it needs SSI_MODE2/3 in the future */ + RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), + + 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_M_REG(gen, SSI, SSICR, 0x00, 0x40), + RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), + RSND_GEN2_M_REG(gen, SSI, SSITDR, 0x08, 0x40), + RSND_GEN2_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40), + RSND_GEN2_M_REG(gen, SSI, SSIWSR, 0x20, 0x40), + }; + + return rsnd_gen_regmap_init(priv, gen, regf); +} + +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); + struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + struct resource *scu_res; + struct resource *adg_res; + struct resource *ssiu_res; + struct resource *ssi_res; + int ret; + + /* + * map address + */ + scu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU); + adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG); + ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU); + ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI); + + gen->base[RSND_GEN2_SCU] = devm_ioremap_resource(dev, scu_res); + gen->base[RSND_GEN2_ADG] = devm_ioremap_resource(dev, adg_res); + gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res); + gen->base[RSND_GEN2_SSI] = devm_ioremap_resource(dev, ssi_res); + if (IS_ERR(gen->base[RSND_GEN2_SCU]) || + IS_ERR(gen->base[RSND_GEN2_ADG]) || + IS_ERR(gen->base[RSND_GEN2_SSIU]) || + IS_ERR(gen->base[RSND_GEN2_SSI])) + return -ENODEV; + + ret = rsnd_gen2_regmap_init(priv, gen); + if (ret < 0) + return ret; + + dev_dbg(dev, "Gen2 device probed\n"); + dev_dbg(dev, "SRU : %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]); + dev_dbg(dev, "SSIU : %08x => %p\n", ssiu_res->start, + gen->base[RSND_GEN2_SSIU]); + dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start, + gen->base[RSND_GEN2_SSI]); + + return 0; +} + /* * Gen1 */ @@ -318,12 +397,14 @@ int rsnd_gen_probe(struct platform_device *pdev, priv->gen = gen; - if (rsnd_is_gen1(priv)) { + ret = -ENODEV; + if (rsnd_is_gen1(priv)) ret = rsnd_gen1_probe(pdev, info, priv); - } else { + else if (rsnd_is_gen2(priv)) + ret = rsnd_gen2_probe(pdev, info, priv); + + if (ret < 0) dev_err(dev, "unknown generation R-Car sound device\n"); - return -ENODEV; - } return ret; } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 63a9d7081c60..bff7b9e53066 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -31,7 +31,7 @@ * see gen1/gen2 for detail */ enum rsnd_reg { - /* SRU/SCU */ + /* SRU/SCU/SSIU */ RSND_REG_SRC_ROUTE_SEL, RSND_REG_SRC_TMG_SEL0, RSND_REG_SRC_TMG_SEL1, @@ -41,6 +41,7 @@ enum rsnd_reg { RSND_REG_SSI_MODE1, RSND_REG_BUSIF_MODE, RSND_REG_BUSIF_ADINR, + RSND_REG_INT_ENABLE, /* ADG */ RSND_REG_BRRA, diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index b71cf9d7dd3f..477465f9507b 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -457,6 +457,9 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; + /* enable PIO interrupt */ + rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); + rsnd_ssi_hw_start(ssi, rdai, io); dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod)); -- cgit v1.2.1 From 60dbb4f17417777fc56cc909c3e89f4d338e8ca8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 3 Dec 2013 22:09:33 -0800 Subject: ASoC: rcar: use devm_clk_get() instead of clk_get() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 477465f9507b..82b04c6f352d 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -652,7 +652,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i); - clk = clk_get(dev, name); + clk = devm_clk_get(dev, name); if (IS_ERR(clk)) return PTR_ERR(clk); @@ -713,7 +713,6 @@ void rsnd_ssi_remove(struct platform_device *pdev, int i; for_each_rsnd_ssi(ssi, priv, i) { - clk_put(ssi->clk); if (rsnd_ssi_dma_available(ssi)) rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod)); } -- cgit v1.2.1 From 1a1c75a7982ca1181bb84bb9e83f9f7c752fb104 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 9 Dec 2013 17:26:01 -0800 Subject: ASoC: rsnd: gen: fixup Gen2 channel size Gen2 has 0 - 9, total 10 channels, not 9 channels. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index bf066f73ef05..d0ab203836de 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -217,11 +217,11 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv, /* single address mapping */ #define RSND_GEN2_S_REG(gen, reg, id, offset) \ - RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 9) + RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10) /* multi address mapping */ #define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \ - RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 9) + RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10) static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) { -- cgit v1.2.1 From a073278228836d7d18fdd6c40b619919c0befb64 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 10 Dec 2013 20:46:59 -0800 Subject: ASoC: fsi: remove original filter from fsi_dma_probe() Remove original filter from fsi_dma_probe(), and use SH-DMA suitable filter. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index b33ca7cd085b..6101055aae1d 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -232,9 +232,9 @@ struct fsi_stream { * these are for DMAEngine */ struct dma_chan *chan; - struct sh_dmae_slave slave; /* see fsi_handler_init() */ struct work_struct work; dma_addr_t dma; + int dma_id; int loop_cnt; int additional_pos; }; @@ -1410,15 +1410,6 @@ static void fsi_dma_do_work(struct work_struct *work) } } -static bool fsi_dma_filter(struct dma_chan *chan, void *param) -{ - struct sh_dmae_slave *slave = param; - - chan->private = slave; - - return true; -} - static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) { schedule_work(&io->work); @@ -1446,15 +1437,34 @@ static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev) { dma_cap_mask_t mask; + int is_play = fsi_stream_is_play(fsi, io); dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave); + io->chan = dma_request_slave_channel_compat(mask, + shdma_chan_filter, (void *)io->dma_id, + dev, is_play ? "tx" : "rx"); + if (io->chan) { + struct dma_slave_config cfg; + int ret; + + cfg.slave_id = io->dma_id; + cfg.dst_addr = 0; /* use default addr */ + cfg.src_addr = 0; /* use default addr */ + cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + + ret = dmaengine_slave_config(io->chan, &cfg); + if (ret < 0) { + dma_release_channel(io->chan); + io->chan = NULL; + } + } + if (!io->chan) { /* switch to PIO handler */ - if (fsi_stream_is_play(fsi, io)) + if (is_play) fsi->playback.handler = &fsi_pio_push_handler; else fsi->capture.handler = &fsi_pio_pop_handler; @@ -1960,7 +1970,7 @@ static void fsi_handler_init(struct fsi_priv *fsi, fsi->capture.priv = fsi; if (info->tx_id) { - fsi->playback.slave.shdma_slave.slave_id = info->tx_id; + fsi->playback.dma_id = info->tx_id; fsi->playback.handler = &fsi_dma_push_handler; } } -- cgit v1.2.1 From e337853ebb46d012c069ca47ba3ce9f4744305ea Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:26:31 -0800 Subject: ASoC: rsnd: add rsnd_adg_set_ssi_clk() and cleanup adg This patch adds rsnd_adg_set_ssi_clk() to access to AUDIO_CLK_SEL0/1/2, and removes last user of rsnd_write/read/bset which is very low level function. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 58 ++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 9430097979a5..55d0394955b2 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,41 +30,41 @@ struct rsnd_adg { i++, (pos) = adg->clk[i]) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) -static enum rsnd_reg rsnd_adg_ssi_reg_get(int id) +static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) { - enum rsnd_reg reg; + int id = rsnd_mod_id(mod); + int shift = (id % 4) * 8; + u32 mask = 0xFF << shift; + + val = val << shift; /* * SSI 8 is not connected to ADG. * it works with SSI 7 */ if (id == 8) - return RSND_REG_MAX; - - if (0 <= id && id <= 3) - reg = RSND_REG_AUDIO_CLK_SEL0; - else if (4 <= id && id <= 7) - reg = RSND_REG_AUDIO_CLK_SEL1; - else - reg = RSND_REG_AUDIO_CLK_SEL2; - - return reg; + return; + + switch (id / 4) { + case 0: + rsnd_mod_bset(mod, AUDIO_CLK_SEL0, mask, val); + break; + case 1: + rsnd_mod_bset(mod, AUDIO_CLK_SEL1, mask, val); + break; + case 2: + rsnd_mod_bset(mod, AUDIO_CLK_SEL2, mask, val); + break; + } } int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - enum rsnd_reg reg; - int id; - /* * "mod" = "ssi" here. * we can get "ssi id" from mod */ - id = rsnd_mod_id(mod); - reg = rsnd_adg_ssi_reg_get(id); - - rsnd_write(priv, mod, reg, 0); + rsnd_adg_set_ssi_clk(mod, 0); return 0; } @@ -75,8 +75,7 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); struct clk *clk; - enum rsnd_reg reg; - int id, shift, i; + int i; u32 data; int sel_table[] = { [CLKA] = 0x1, @@ -125,19 +124,10 @@ found_clock: * This "mod" = "ssi" here. * we can get "ssi id" from mod */ - id = rsnd_mod_id(mod); - reg = rsnd_adg_ssi_reg_get(id); - - dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate); - - /* - * Enable SSIx clock - */ - shift = (id % 4) * 8; + rsnd_adg_set_ssi_clk(mod, data); - rsnd_bset(priv, mod, reg, - 0xFF << shift, - data << shift); + dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", + rsnd_mod_id(mod), i, rate); return 0; } -- cgit v1.2.1 From 729aca51a19f2e2b3404c29b82df61d714150a49 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:26:44 -0800 Subject: ASoC: rsnd: tidyup ssi comment we can check rsnd_ssi_init(), not, rsnd_ssi_start() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 82b04c6f352d..aff5b76d1fd5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -209,7 +209,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, /* * this driver is assuming that * system word is 64fs (= 2 x 32bit) - * see rsnd_ssi_start() + * see rsnd_ssi_init() */ main_rate = rate / adg_clk_div_table[i] * 32 * 2 * ssi_clk_mul_table[j]; -- cgit v1.2.1 From 690ef81ebe02a43991b0fcb418d77b8420346cfd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:27:03 -0800 Subject: ASoC: rsnd: tidyup register naming Use correct register name which appears in the datasheet Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 4 ++-- sound/soc/sh/rcar/rsnd.h | 4 ++-- sound/soc/sh/rcar/scu.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index d0ab203836de..862758d3ec06 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -314,11 +314,11 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08), RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c), RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10), - RSND_GEN1_S_REG(gen, SRU, SRC_CTRL, 0xc0), + 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, BUSIF_ADINR, 0x214, 0x40), + RSND_GEN1_M_REG(gen, SRU, SRC_ADINR, 0x214, 0x40), RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index bff7b9e53066..d5c0182c8e50 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -36,12 +36,12 @@ enum rsnd_reg { RSND_REG_SRC_TMG_SEL0, RSND_REG_SRC_TMG_SEL1, RSND_REG_SRC_TMG_SEL2, - RSND_REG_SRC_CTRL, + RSND_REG_SRC_ROUTE_CTRL, RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, RSND_REG_BUSIF_MODE, - RSND_REG_BUSIF_ADINR, RSND_REG_INT_ENABLE, + RSND_REG_SRC_ADINR, /* ADG */ RSND_REG_BRRA, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 1ab1bce6be7f..187f7dc30369 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -115,7 +115,7 @@ static int rsnd_scu_set_mode(struct rsnd_priv *priv, if (rsnd_is_gen1(priv)) { val = (1 << id); - rsnd_mod_bset(mod, SRC_CTRL, val, val); + rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); } return 0; @@ -141,7 +141,7 @@ static int rsnd_scu_set_hpbif(struct rsnd_priv *priv, } rsnd_mod_write(mod, BUSIF_MODE, 1); - rsnd_mod_write(mod, BUSIF_ADINR, adinr); + rsnd_mod_write(mod, SRC_ADINR, adinr); return 0; } -- cgit v1.2.1 From 7808aa30d6cf366e5f627dcbf7c84f9dc6e602ab Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:27:19 -0800 Subject: ASoC: rsnd: make sure variable name for 44.1kHz/48kHz This driver is assuming that RBGA is used as source clock of 44.1kHz category, and RBGB is used as source clock of 48kHz category. This patch clarifies the variable name. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 55d0394955b2..2e71a7bda4c2 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -19,8 +19,8 @@ struct rsnd_adg { struct clk *clk[CLKMAX]; - int rate_of_441khz_div_6; - int rate_of_48khz_div_6; + int rbga_rate_for_441khz_div_6; /* RBGA */ + int rbgb_rate_for_48khz_div_6; /* RBGB */ u32 ckr; }; @@ -101,12 +101,12 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) /* * find 1/6 clock from BRGA/BRGB */ - if (rate == adg->rate_of_441khz_div_6) { + if (rate == adg->rbga_rate_for_441khz_div_6) { data = 0x10; goto found_clock; } - if (rate == adg->rate_of_48khz_div_6) { + if (rate == adg->rbgb_rate_for_48khz_div_6) { data = 0x20; goto found_clock; } @@ -156,8 +156,8 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) * rsnd_adg_ssi_clk_try_start() */ ckr = 0; - adg->rate_of_441khz_div_6 = 0; - adg->rate_of_48khz_div_6 = 0; + adg->rbga_rate_for_441khz_div_6 = 0; + adg->rbgb_rate_for_48khz_div_6 = 0; for_each_rsnd_clk(clk, adg, i) { rate = clk_get_rate(clk); @@ -165,14 +165,14 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) continue; /* RBGA */ - if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) { - adg->rate_of_441khz_div_6 = rate / 6; + if (!adg->rbga_rate_for_441khz_div_6 && (0 == rate % 44100)) { + adg->rbga_rate_for_441khz_div_6 = rate / 6; ckr |= brg_table[i] << 20; } /* RBGB */ - if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) { - adg->rate_of_48khz_div_6 = rate / 6; + if (!adg->rbgb_rate_for_48khz_div_6 && (0 == rate % 48000)) { + adg->rbgb_rate_for_48khz_div_6 = rate / 6; ckr |= brg_table[i] << 16; } } -- cgit v1.2.1 From 2582718cb6bd620d37a54db885c75bfe4822db45 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:27:37 -0800 Subject: ASoC: rsnd: route setting is needed only Gen1 Renesas sound has SRC (= Sampling Rate Converter), but, the HW implementation depends on its generation. It was part of SRU on Gen1, and SCU on Gen2. This SCU needs DMA transfer to use it. Current rsnd driver is using it as DMA transfer buffer (= no rate convert), and Gen1 is only supported at this point. This patch cleanup it with focusing about SRC and Gen2 part. rsnd_scu_set_route() is needed only Gen1. This patch renames it to rsnd_scu_set_route_if_gen1() and it adds comment to rsnd_reg member in order to clarify it is used for Gen1. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 10 +++++----- sound/soc/sh/rcar/scu.c | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index d5c0182c8e50..a14bc9274b3f 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -32,11 +32,11 @@ */ enum rsnd_reg { /* SRU/SCU/SSIU */ - RSND_REG_SRC_ROUTE_SEL, - RSND_REG_SRC_TMG_SEL0, - RSND_REG_SRC_TMG_SEL1, - RSND_REG_SRC_TMG_SEL2, - RSND_REG_SRC_ROUTE_CTRL, + 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_SSI_MODE0, RSND_REG_SSI_MODE1, RSND_REG_BUSIF_MODE, diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 187f7dc30369..7642ec52b590 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -36,7 +36,8 @@ struct rsnd_scu { ((pos) = (struct rsnd_scu *)(priv)->scu + i); \ i++) -static int rsnd_scu_set_route(struct rsnd_priv *priv, +/* Gen1 only */ +static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -174,7 +175,8 @@ static int rsnd_scu_start(struct rsnd_mod *mod, } /* it use DMA transter */ - ret = rsnd_scu_set_route(priv, mod, rdai, io); + + ret = rsnd_src_set_route_if_gen1(priv, mod, rdai, io); if (ret < 0) return ret; -- cgit v1.2.1 From af8a478821345fd264fd2294e80f5b0a28a518bc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:28:04 -0800 Subject: ASoC: rsnd: add rsnd_scu_transfer_start() Renesas sound has SRC (= Sampling Rate Converter), but, the HW implementation depends on its generation. It was part of SRU on Gen1, and SCU on Gen2. This SCU needs DMA transfer to use it. Current rsnd driver is using it as DMA transfer buffer (= no rate convert), and Gen1 is only supported at this point. This patch cleanup it with focusing about SRC and Gen2 part. SRC_CTRL/BUSIF_MODE are used for transfer start. This patch adds rsnd_scu_transfer_start() and merge these Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 7642ec52b590..3d8b57b1630b 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -106,22 +106,6 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, return 0; } -static int rsnd_scu_set_mode(struct rsnd_priv *priv, - struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) -{ - 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); - } - - return 0; -} - static int rsnd_scu_set_hpbif(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_dai *rdai, @@ -141,12 +125,29 @@ static int rsnd_scu_set_hpbif(struct rsnd_priv *priv, return -EIO; } - rsnd_mod_write(mod, BUSIF_MODE, 1); rsnd_mod_write(mod, SRC_ADINR, adinr); 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) +{ + 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); + } + + rsnd_mod_write(mod, BUSIF_MODE, 1); + + return 0; +} + bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod) { struct rsnd_scu *scu = rsnd_mod_to_scu(mod); @@ -180,11 +181,11 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_set_mode(priv, mod, rdai, io); + ret = rsnd_scu_set_hpbif(priv, mod, rdai, io); if (ret < 0) return ret; - ret = rsnd_scu_set_hpbif(priv, mod, rdai, io); + ret = rsnd_scu_transfer_start(priv, mod, rdai, io); if (ret < 0) return ret; -- cgit v1.2.1 From 52ea2a79f440740b57925e729a59337414b4c300 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:28:19 -0800 Subject: ASoC: rsnd: INT_ENABLE is needed only Gen2 INT_ENABLE is needed only Gen2. rsnd_mod_write() do nothing on Gen1, but it is confusable. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 2 +- sound/soc/sh/rcar/ssi.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a14bc9274b3f..3774dfcfaf0f 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -40,7 +40,7 @@ enum rsnd_reg { RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE1, RSND_REG_BUSIF_MODE, - RSND_REG_INT_ENABLE, + RSND_REG_INT_ENABLE, /* for Gen2 */ RSND_REG_SRC_ADINR, /* ADG */ diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index aff5b76d1fd5..01b5cf945d61 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -457,8 +457,9 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, /* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN; - /* enable PIO interrupt */ - rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000); + /* 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); -- cgit v1.2.1 From 99feec32f26a3c267f89ce48db4bd36650a95f7f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:28:31 -0800 Subject: ASoC: rsnd: scu cleanup: add rsnd_scu_rate_ctrl() Renesas sound has SRC (= Sampling Rate Converter), but, the HW implementation depends on its generation. It was part of SRU on Gen1, and SCU on Gen2. This SCU needs DMA transfer to use it. Current rsnd driver is using it as DMA transfer buffer (= no rate convert), and Gen1 is only supported at this point. This patch cleanup it with focusing about SRC and Gen2 part. rsnd_scu_set_hpbif() is renamed to rsnd_scu_rate_ctrl(), since its naming doesn't indicate the function meaning. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/scu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 3d8b57b1630b..5f4f57206faf 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -106,7 +106,7 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, return 0; } -static int rsnd_scu_set_hpbif(struct rsnd_priv *priv, +static int rsnd_scu_rate_ctrl(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) @@ -181,7 +181,7 @@ static int rsnd_scu_start(struct rsnd_mod *mod, if (ret < 0) return ret; - ret = rsnd_scu_set_hpbif(priv, mod, rdai, io); + ret = rsnd_scu_rate_ctrl(priv, mod, rdai, io); if (ret < 0) return ret; -- cgit v1.2.1 From adcf7d5e7605e8134a99d415b7afd13f03c4bf23 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:28:39 -0800 Subject: ASoC: rsnd: tidyup rsnd_ssi_master_clk_start() parameter Renesas sound has SRC (= Sampling Rate Converter), but, the HW implementation depends on its generation. It was part of SRU on Gen1, and SCU on Gen2. This SCU needs DMA transfer to use it. Current rsnd driver is using it as DMA transfer buffer (= no rate convert), and Gen1 is only supported at this point. This patch cleanup it with focusing about SRC and Gen2 part. ssi clock which is calculated from rsnd_ssi_master_clk_start() should have flexibility since Renesas sound has SRC (= Sampling Rate Converter). But current implementation is using runtime->rate directly. This patch tidyup rsnd_ssi_master_clk_start() parameter as preparation of future SRC support Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 01b5cf945d61..2db9711549f5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -187,9 +187,10 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, } static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, - unsigned int rate) + struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); int i, j, ret; int adg_clk_div_table[] = { @@ -199,6 +200,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 = runtime->rate; /* * Find best clock, and try to start ADG @@ -251,14 +253,10 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, clk_enable(ssi->clk); if (rsnd_rdai_is_clk_master(rdai)) { - struct snd_pcm_runtime *runtime; - - runtime = rsnd_io_to_runtime(io); - if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, rdai, io); else - rsnd_ssi_master_clk_start(ssi, runtime->rate); + rsnd_ssi_master_clk_start(ssi, io); } } -- cgit v1.2.1 From ef749400434cefd14fe02fe3de9e9f0125b2256d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 19 Dec 2013 19:28:51 -0800 Subject: ASoC: rsnd: add SRC (Sampling Rate Converter) support This patch adds SRC support to Renesas sound driver. SRC converts sampling rate between codec <-> cpu. It needs special codec chip, or very simple DA/AD converter to use it. This patch was tested via ak4554 codec, and supports Gen1 only at this point. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 73 +++++++++++++++++++++++ sound/soc/sh/rcar/gen.c | 10 ++++ sound/soc/sh/rcar/rsnd.h | 18 ++++++ sound/soc/sh/rcar/scu.c | 152 ++++++++++++++++++++++++++++++++++++++++++++--- sound/soc/sh/rcar/ssi.c | 2 +- 5 files changed, 247 insertions(+), 8 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 2e71a7bda4c2..a53235c4d1b0 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -30,6 +30,79 @@ 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) +{ + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct device *dev = rsnd_priv_to_dev(priv); + int idx, sel, div, shift; + u32 mask, val; + int id = rsnd_mod_id(mod); + unsigned int sel_rate [] = { + clk_get_rate(adg->clk[CLKA]), /* 000: CLKA */ + clk_get_rate(adg->clk[CLKB]), /* 001: CLKB */ + clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */ + 0, /* 011: MLBCLK (not used) */ + adg->rbga_rate_for_441khz_div_6,/* 100: RBGA */ + adg->rbgb_rate_for_48khz_div_6, /* 101: RBGB */ + }; + + /* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */ + for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { + for (div = 128, idx = 0; + div <= 2048; + div *= 2, idx++) { + if (src_rate == sel_rate[sel] / div) { + val = (idx << 4) | sel; + goto find_rate; + } + } + } + dev_err(dev, "can't find convert src clk\n"); + return -EINVAL; + +find_rate: + shift = (id % 4) * 8; + mask = 0xFF << shift; + val = val << shift; + + dev_dbg(dev, "adg convert src clk = %02x\n", val); + + switch (id / 4) { + case 0: + rsnd_mod_bset(mod, AUDIO_CLK_SEL3, mask, val); + break; + case 1: + rsnd_mod_bset(mod, AUDIO_CLK_SEL4, mask, val); + break; + case 2: + rsnd_mod_bset(mod, AUDIO_CLK_SEL5, mask, val); + break; + } + + /* + * Gen1 doesn't need dst_rate settings, + * since it uses SSI WS pin. + * see also rsnd_src_set_route_if_gen1() + */ + + 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/gen.c b/sound/soc/sh/rcar/gen.c index 862758d3ec06..add088bd4b2a 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -318,13 +318,23 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) 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_ROUTE_MODE0,0x50, 0x8), + RSND_GEN1_M_REG(gen, SRU, SRC_SWRSR, 0x200, 0x40), + RSND_GEN1_M_REG(gen, SRU, SRC_SRCIR, 0x204, 0x40), RSND_GEN1_M_REG(gen, SRU, SRC_ADINR, 0x214, 0x40), + RSND_GEN1_M_REG(gen, SRU, SRC_IFSCR, 0x21c, 0x40), + RSND_GEN1_M_REG(gen, SRU, SRC_IFSVR, 0x220, 0x40), + RSND_GEN1_M_REG(gen, SRU, SRC_SRCCR, 0x224, 0x40), + RSND_GEN1_M_REG(gen, SRU, SRC_MNFSR, 0x228, 0x40), RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00), RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04), RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08), RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c), + RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20), RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 3774dfcfaf0f..4ca66cd899c8 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -41,7 +41,14 @@ enum rsnd_reg { RSND_REG_SSI_MODE1, RSND_REG_BUSIF_MODE, RSND_REG_INT_ENABLE, /* for Gen2 */ + RSND_REG_SRC_ROUTE_MODE0, + RSND_REG_SRC_SWRSR, + RSND_REG_SRC_SRCIR, RSND_REG_SRC_ADINR, + RSND_REG_SRC_IFSCR, + RSND_REG_SRC_IFSVR, + RSND_REG_SRC_SRCCR, + RSND_REG_SRC_MNFSR, /* ADG */ RSND_REG_BRRA, @@ -50,6 +57,9 @@ enum rsnd_reg { 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 */ /* SSI */ RSND_REG_SSICR, @@ -227,6 +237,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); /* * R-Car sound priv @@ -280,6 +294,10 @@ 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); + #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 5f4f57206faf..1406dd8d9ed2 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c @@ -13,9 +13,13 @@ struct rsnd_scu { struct rsnd_scu_platform_info *info; /* rcar_snd.h */ struct rsnd_mod mod; + 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 /* * ADINR @@ -26,6 +30,15 @@ struct rsnd_scu { #define OTBL_18 (6 << 16) #define OTBL_16 (8 << 16) +/* + * image of SRC (Sampling Rate Converter) + * + * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+ + * 48kHz <-> | SRC | <------> | SSI | <-----> | codec | + * 44.1kHz <-> +-----+ +-----+ +-------+ + * ... + * + */ #define rsnd_mod_to_scu(_mod) \ container_of((_mod), struct rsnd_scu, mod) @@ -56,7 +69,7 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; - + struct rsnd_scu *scu = rsnd_mod_to_scu(mod); u32 mask; u32 val; int shift; @@ -86,9 +99,18 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, */ shift = (id % 4) * 8; mask = 0x1F << shift; - if (8 == id) /* SRU8 is very special */ + + /* + * 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) + */ + if (rsnd_scu_convert_rate(scu)) /* use ADG */ + val = 0; + else if (8 == id) /* use SSI WS, but SRU8 is special */ val = id << shift; - else + else /* use SSI WS */ val = (id + 1) << shift; switch (id / 4) { @@ -106,14 +128,45 @@ static int rsnd_src_set_route_if_gen1(struct rsnd_priv *priv, return 0; } -static int rsnd_scu_rate_ctrl(struct rsnd_priv *priv, +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_convert_rate_ctrl(struct rsnd_priv *priv, 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; + /* 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; @@ -124,9 +177,42 @@ static int rsnd_scu_rate_ctrl(struct rsnd_priv *priv, default: return -EIO; } - rsnd_mod_write(mod, SRC_ADINR, adinr); + 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); + + /* Set initial value of IFS */ + rsnd_mod_write(mod, SRC_IFSVR, fsrate); + + /* 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, fsrate / 100 * 98); + + 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 */ + rsnd_mod_write(mod, SRC_SRCIR, 0); + + /* use DMA transfer */ + rsnd_mod_write(mod, BUSIF_MODE, 1); + return 0; } @@ -135,6 +221,7 @@ static int rsnd_scu_transfer_start(struct rsnd_priv *priv, 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; @@ -143,7 +230,28 @@ static int rsnd_scu_transfer_start(struct rsnd_priv *priv, rsnd_mod_bset(mod, SRC_ROUTE_CTRL, val, val); } - rsnd_mod_write(mod, BUSIF_MODE, 1); + 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; } @@ -161,6 +269,7 @@ static int rsnd_scu_start(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); struct device *dev = rsnd_priv_to_dev(priv); int ret; @@ -175,13 +284,15 @@ static int rsnd_scu_start(struct rsnd_mod *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; - ret = rsnd_scu_rate_ctrl(priv, mod, rdai, io); + ret = rsnd_scu_convert_rate_ctrl(priv, mod, rdai, io); if (ret < 0) return ret; @@ -194,9 +305,27 @@ static int rsnd_scu_start(struct rsnd_mod *mod, return 0; } +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); + + if (!rsnd_scu_hpbif_is_enable(mod)) + return 0; + + rsnd_scu_transfer_stop(priv, mod, rdai, io); + + clk_disable(scu->clk); + + return 0; +} + static struct rsnd_mod_ops rsnd_scu_ops = { .name = "scu", .start = rsnd_scu_start, + .stop = rsnd_scu_stop, }; struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id) @@ -212,6 +341,8 @@ int rsnd_scu_probe(struct platform_device *pdev, { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_scu *scu; + struct clk *clk; + char name[RSND_SCU_NAME_SIZE]; int i, nr; /* @@ -228,9 +359,16 @@ int rsnd_scu_probe(struct platform_device *pdev, 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); + rsnd_mod_init(priv, &scu->mod, &rsnd_scu_ops, i); scu->info = &info->scu_info[i]; + scu->clk = clk; 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 2db9711549f5..b7cd06be9436 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -200,7 +200,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 = runtime->rate; + unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime); /* * Find best clock, and try to start ADG -- cgit v1.2.1