| From e055532069fb171e266999873458ac552e718a26 Mon Sep 17 00:00:00 2001 |
| From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| 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 <kuninori.morimoto.gx@renesas.com> |
| Signed-off-by: Mark Brown <broonie@linaro.org> |
| (cherry picked from commit 1b7b08efbe7419cc3e082f2b5ec8ae89f7af43d1) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| 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(-) |
| |
| 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; |
| -- |
| 2.1.2 |
| |