(cherry picked from commit ba9c949f797aa3af56303445812a452144c61c35)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
- 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 => src.c} | 265 +++++++++++++++++++------------------
- sound/soc/sh/rcar/ssi.c | 6 +-
- 6 files changed, 175 insertions(+), 166 deletions(-)
+ 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(-)
rename sound/soc/sh/rcar/{scu.c => src.c} (63%)
-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 {
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 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 @@
* ...
*
*
-@@ -572,7 +572,7 @@ static int rsnd_path_init(struct rsnd_priv *priv,
+@@ -572,7 +572,7 @@ static int rsnd_path_init(struct rsnd_pr
struct rsnd_dai_platform_info *dai_info = rdai->info;
int ret;
int ssi_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,
+@@ -587,8 +587,8 @@ static int rsnd_path_init(struct rsnd_pr
if (dai_info) {
if (rsnd_is_enable_path(io, ssi))
ssi_id = rsnd_info_id(priv, io, ssi);
} 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,
+@@ -596,14 +596,14 @@ static int rsnd_path_init(struct rsnd_pr
rsnd_dai_is_play(rdai, io));
if (!mod)
return 0;
ret = rsnd_dai_connect(mod, io);
if (ret < 0)
return ret;
-@@ -806,7 +806,7 @@ static int rsnd_probe(struct platform_device *pdev)
+@@ -805,7 +805,7 @@ static int rsnd_probe(struct platform_de
struct rsnd_priv *priv) = {
rsnd_gen_probe,
rsnd_ssi_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,
+@@ -160,7 +160,7 @@ void rsnd_dma_quit(struct rsnd_priv *pr
* R-Car sound mod
*/
enum rsnd_mod_type {
/*
* R-Car SSI
-diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/src.c
-similarity index 63%
-rename from sound/soc/sh/rcar/scu.c
-rename to sound/soc/sh/rcar/src.c
-index 3526a5c2f608..ea6a214985d0 100644
--- a/sound/soc/sh/rcar/scu.c
-+++ b/sound/soc/sh/rcar/src.c
-@@ -1,5 +1,5 @@
- /*
++++ /dev/null
+@@ -1,682 +0,0 @@
+-/*
- * Renesas R-Car SCU support
-+ * Renesas R-Car SRC support
- *
- * Copyright (C) 2013 Renesas Solutions Corp.
- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
-@@ -10,13 +10,13 @@
- */
- #include "rsnd.h"
-
+- *
+- * Copyright (C) 2013 Renesas Solutions Corp.
+- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+- *
+- * 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_src {
-+ struct rsnd_src_platform_info *info; /* rcar_snd.h */
- struct rsnd_mod mod;
- struct clk *clk;
- };
-
+- struct rsnd_mod mod;
+- struct clk *clk;
+-};
+-
-#define RSND_SCU_NAME_SIZE 16
-+#define RSND_SRC_NAME_SIZE 16
-
- /*
- * ADINR
-@@ -27,19 +27,19 @@ struct rsnd_scu {
- #define OTBL_18 (6 << 16)
- #define OTBL_16 (8 << 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) \
- (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;
+-}
+--- /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 <kuninori.morimoto.gx@renesas.com>
++ *
++ * 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) \
+ (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_scu(pos, priv, i) \
++
+#define for_each_rsnd_src(pos, priv, i) \
- for ((i) = 0; \
-- ((i) < rsnd_scu_nr(priv)) && \
-- ((pos) = (struct rsnd_scu *)(priv)->scu + i); \
++ for ((i) = 0; \
+ ((i) < rsnd_src_nr(priv)) && \
+ ((pos) = (struct rsnd_src *)(priv)->src + i); \
- i++)
-
-
-@@ -54,7 +54,7 @@ struct rsnd_scu {
- */
-
- /*
-- * scu.c is caring...
++ i++)
++
++
++/*
++ * image of SRC (Sampling Rate Converter)
++ *
++ * 96kHz <-> +-----+ 48kHz +-----+ 48kHz +-------+
++ * 48kHz <-> | SRC | <------> | SSI | <-----> | codec |
++ * 44.1kHz <-> +-----+ +-----+ +-------+
++ * ...
++ *
++ */
++
++/*
+ * src.c is caring...
- *
- * Gen1
- *
-@@ -63,7 +63,7 @@ struct rsnd_scu {
- *
- * Gen2
- *
-- * [mem] -> [SCU] -> [SSIU] -> [SSI]
++ *
++ * Gen1
++ *
++ * [mem] -> [SRU] -> [SSI]
++ * |--------|
++ *
++ * Gen2
++ *
+ * [mem] -> [SRC] -> [SSIU] -> [SSI]
- * |-----------------|
- */
-
-@@ -79,34 +79,34 @@ struct rsnd_scu {
- * but SRC bypass mode needs SSI_MODE0 only.
- *
- * This driver request
-- * struct rsnd_scu_platform_info {
++ * |-----------------|
++ */
++
++/*
++ * 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_scu_hpbif_is_enable() will be true
-- * if flags had RSND_SCU_USE_HPBIF,
++ * 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_scu_convert_rate() indicates
++ * 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_scu_platform_info info = {
++ * 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_scu_platform_info info = {
-- * .flags = RSND_SCU_USE_HPBIF,
++ * .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_scu_platform_info info = {
-- * .flags = RSND_SCU_USE_HPBIF,
++ * .convert_rate = 48000,
++ * };
++ *
++ * ex) uses SRC bypass mode
+ * struct rsnd_src_platform_info info = {
+ * .flags = RSND_SRC_USE_HPBIF,
- * .convert_rate = 0,
- * };
- *
-@@ -115,28 +115,28 @@ struct rsnd_scu {
- /*
- * Gen1/Gen2 common functions
- */
--int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod,
++ * .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 *scu_mod = rsnd_io_to_mod_scu(io);
++ 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_scu = 0;
++ 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_scu = !!scu_mod;
++
++ /*
++ * SSI_MODE0
++ */
++ if (info->dai_info) {
+ has_src = !!src_mod;
- } else {
-- struct rsnd_scu *scu = rsnd_mod_to_scu(scu_mod);
-- has_scu = rsnd_scu_hpbif_is_enable(scu);
++ } 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_scu ? 0 : (1 << ssi_id));
++ }
++
++ rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id),
+ has_src ? 0 : (1 << ssi_id));
-
- /*
- * SSI_MODE1
-@@ -165,7 +165,7 @@ int rsnd_scu_ssi_mode_init(struct rsnd_mod *ssi_mod,
- return 0;
- }
-
--int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod,
++
++ /*
++ * 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)
- {
-@@ -178,33 +178,33 @@ int rsnd_scu_enable_ssi_irq(struct rsnd_mod *ssi_mod,
- return 0;
- }
-
--unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv,
++ 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_scu *scu;
++ struct rsnd_dai_stream *io,
++ struct snd_pcm_runtime *runtime)
++{
+ struct rsnd_src *src;
- unsigned int rate;
-
-- scu = rsnd_mod_to_scu(rsnd_io_to_mod_scu(io));
++ 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_scu_convert_rate(scu);
++
++ /*
++ * 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_scu_set_convert_rate(struct rsnd_mod *mod,
++ 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_scu *scu = rsnd_mod_to_scu(mod);
-- u32 convert_rate = rsnd_scu_convert_rate(scu);
++ 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;
-
-@@ -217,7 +217,7 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod,
-
- /*
- * Initialize the operation of the SRC internal circuits
-- * see rsnd_scu_start()
++ 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);
-
-@@ -248,61 +248,61 @@ static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod,
- return 0;
- }
-
--static int rsnd_scu_init(struct rsnd_mod *mod,
++ */
++ 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_scu *scu = rsnd_mod_to_scu(mod);
++ struct rsnd_dai *rdai,
++ struct rsnd_dai_stream *io)
++{
+ struct rsnd_src *src = rsnd_mod_to_src(mod);
-
-- clk_enable(scu->clk);
++
+ clk_enable(src->clk);
-
- return 0;
- }
-
--static int rsnd_scu_quit(struct rsnd_mod *mod,
++
++ return 0;
++}
++
+static int rsnd_src_quit(struct rsnd_mod *mod,
- struct rsnd_dai *rdai,
- struct rsnd_dai_stream *io)
- {
-- struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
++ struct rsnd_dai *rdai,
++ struct rsnd_dai_stream *io)
++{
+ struct rsnd_src *src = rsnd_mod_to_src(mod);
-
-- clk_disable(scu->clk);
++
+ clk_disable(src->clk);
-
- return 0;
- }
-
--static int rsnd_scu_start(struct rsnd_mod *mod,
++
++ return 0;
++}
++
+static int rsnd_src_start(struct rsnd_mod *mod,
- struct rsnd_dai *rdai,
- struct rsnd_dai_stream *io)
- {
-- struct rsnd_scu *scu = rsnd_mod_to_scu(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_scu_set_convert_rate()
++
++ /*
++ * Cancel the initialization and operate the SRC function
+ * see rsnd_src_set_convert_rate()
- */
- rsnd_mod_write(mod, SRC_SRCIR, 0);
-
-- if (rsnd_scu_convert_rate(scu))
-+ if (rsnd_src_convert_rate(src))
- rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1);
-
- return 0;
- }
-
-
--static int rsnd_scu_stop(struct rsnd_mod *mod,
++ */
++ 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_scu *scu = rsnd_mod_to_scu(mod);
++ struct rsnd_dai *rdai,
++ struct rsnd_dai_stream *io)
++{
+ struct rsnd_src *src = rsnd_mod_to_src(mod);
-
-- if (rsnd_scu_convert_rate(scu))
++
+ if (rsnd_src_convert_rate(src))
- rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0);
-
- return 0;
- }
-
--static struct rsnd_mod_ops rsnd_scu_non_ops = {
-- .name = "scu (non)",
++ rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0);
++
++ return 0;
++}
++
+static struct rsnd_mod_ops rsnd_src_non_ops = {
+ .name = "src (non)",
- };
-
- /*
-@@ -312,7 +312,7 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
- struct rsnd_dai *rdai,
- struct rsnd_dai_stream *io)
- {
-- struct scu_route_config {
++};
++
++/*
++ * 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[] = {
-@@ -346,14 +346,14 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
- return 0;
- }
-
--static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod,
++ 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_scu *scu = rsnd_mod_to_scu(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_scu_convert_rate(scu);
++ struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+ u32 convert_rate = rsnd_src_convert_rate(src);
- u32 mask;
- u32 val;
- int shift;
-@@ -405,13 +405,13 @@ static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod,
- return 0;
- }
-
--static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod,
++ 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_scu_set_convert_rate(mod, rdai, io);
++ 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;
-
-@@ -427,13 +427,13 @@ static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod,
- return 0;
- }
-
--static int rsnd_scu_init_gen1(struct rsnd_mod *mod,
++ 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_scu_init(mod, rdai, io);
++ struct rsnd_dai *rdai,
++ struct rsnd_dai_stream *io)
++{
++ int ret;
++
+ ret = rsnd_src_init(mod, rdai, io);
- if (ret < 0)
- return ret;
-
-@@ -441,18 +441,18 @@ static int rsnd_scu_init_gen1(struct rsnd_mod *mod,
- if (ret < 0)
- return ret;
-
-- ret = rsnd_scu_set_convert_rate_gen1(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_scu_set_convert_timing_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_scu_start_gen1(struct rsnd_mod *mod,
++ 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)
- {
-@@ -460,10 +460,10 @@ static int rsnd_scu_start_gen1(struct rsnd_mod *mod,
-
- rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id));
-
-- return rsnd_scu_start(mod, rdai, io);
++ 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_scu_stop_gen1(struct rsnd_mod *mod,
++}
++
+static int rsnd_src_stop_gen1(struct rsnd_mod *mod,
- struct rsnd_dai *rdai,
- struct rsnd_dai_stream *io)
- {
-@@ -471,27 +471,27 @@ static int rsnd_scu_stop_gen1(struct rsnd_mod *mod,
-
- rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0);
-
-- return rsnd_scu_stop(mod, rdai, io);
++ 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_scu_gen1_ops = {
++}
++
+static struct rsnd_mod_ops rsnd_src_gen1_ops = {
- .name = "sru (gen1)",
-- .init = rsnd_scu_init_gen1,
-- .quit = rsnd_scu_quit,
-- .start = rsnd_scu_start_gen1,
-- .stop = rsnd_scu_stop_gen1,
++ .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_scu_set_convert_rate_gen2(struct rsnd_mod *mod,
++};
++
++/*
++ * 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_scu_set_convert_rate(mod, rdai, io);
++ 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;
-
-@@ -506,13 +506,13 @@ static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod,
- return 0;
- }
-
--static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod,
++ 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_scu *scu = rsnd_mod_to_scu(mod);
-- u32 convert_rate = rsnd_scu_convert_rate(scu);
++ 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)
-@@ -525,34 +525,34 @@ static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod,
- return ret;
- }
-
--static int rsnd_scu_probe_gen2(struct rsnd_mod *mod,
++ 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_scu *scu = rsnd_mod_to_scu(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, scu);
++ 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,
-- scu->info->dma_id);
++ 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, "SCU DMA failed\n");
++ if (ret < 0)
+ dev_err(dev, "SRC DMA failed\n");
-
- return ret;
- }
-
--static int rsnd_scu_remove_gen2(struct rsnd_mod *mod,
++
++ return ret;
++}
++
+static int rsnd_src_remove_gen2(struct rsnd_mod *mod,
- struct rsnd_dai *rdai,
- struct rsnd_dai_stream *io)
- {
-@@ -561,121 +561,126 @@ static int rsnd_scu_remove_gen2(struct rsnd_mod *mod,
- return 0;
- }
-
--static int rsnd_scu_init_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_scu_init(mod, rdai, io);
++ 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_scu_set_convert_rate_gen2(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_scu_set_convert_timing_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_scu_start_gen2(struct rsnd_mod *mod,
++ 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_scu *scu = rsnd_mod_to_scu(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(&scu->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_scu_start(mod, rdai, io);
++
++ rsnd_mod_write(mod, SSI_CTRL, 0x1);
++ rsnd_mod_write(mod, SRC_CTRL, 0x11);
++
+ return rsnd_src_start(mod, rdai, io);
- }
-
--static int rsnd_scu_stop_gen2(struct rsnd_mod *mod,
++}
++
+static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
- struct rsnd_dai *rdai,
- struct rsnd_dai_stream *io)
- {
-- struct rsnd_scu *scu = rsnd_mod_to_scu(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(&scu->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_scu_stop(mod, rdai, io);
++
+ return rsnd_src_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,
++}
++
+static struct rsnd_mod_ops rsnd_src_gen2_ops = {
+ .name = "src (gen2)",
+ .probe = rsnd_src_probe_gen2,
+ .quit = rsnd_src_quit,
+ .start = rsnd_src_start_gen2,
+ .stop = rsnd_src_stop_gen2,
- };
-
--struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id)
++};
++
+struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
- {
-- if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv)))
++{
+ if (WARN_ON(id < 0 || id >= rsnd_src_nr(priv)))
- id = 0;
-
-- return &((struct rsnd_scu *)(priv->scu) + id)->mod;
++ id = 0;
++
+ return &((struct rsnd_src *)(priv->src) + id)->mod;
- }
-
--int rsnd_scu_probe(struct platform_device *pdev,
++}
++
+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_scu *scu;
++ 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_SCU_NAME_SIZE];
++ struct rsnd_mod_ops *ops;
++ struct clk *clk;
+ char name[RSND_SRC_NAME_SIZE];
- int i, nr;
-
- /*
-- * init SCU
++ int i, nr;
++
++ /*
+ * init SRC
- */
-- nr = info->scu_info_nr;
++ */
+ nr = info->src_info_nr;
- if (!nr)
- return 0;
-
-- scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL);
-- if (!scu) {
-- dev_err(dev, "SCU allocate failed\n");
++ 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->scu_nr = nr;
-- priv->scu = scu;
++ return -ENOMEM;
++ }
++
+ priv->src_nr = nr;
+ priv->src = src;
-
-- for_each_rsnd_scu(scu, priv, i) {
-- snprintf(name, RSND_SCU_NAME_SIZE, "scu.%d", i);
++
+ for_each_rsnd_src(src, priv, i) {
+ snprintf(name, RSND_SRC_NAME_SIZE, "src.%d", i);
-
- clk = devm_clk_get(dev, name);
++
++ 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);
-
-- scu->info = &info->scu_info[i];
-- scu->clk = clk;
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
+ src->info = &info->src_info[i];
+ src->clk = clk;
-
-- ops = &rsnd_scu_non_ops;
-- if (rsnd_scu_hpbif_is_enable(scu)) {
++
+ ops = &rsnd_src_non_ops;
+ if (rsnd_src_hpbif_is_enable(src)) {
- if (rsnd_is_gen1(priv))
-- ops = &rsnd_scu_gen1_ops;
++ if (rsnd_is_gen1(priv))
+ ops = &rsnd_src_gen1_ops;
- if (rsnd_is_gen2(priv))
-- ops = &rsnd_scu_gen2_ops;
++ if (rsnd_is_gen2(priv))
+ ops = &rsnd_src_gen2_ops;
- }
-
-- rsnd_mod_init(priv, &scu->mod, ops, RSND_MOD_SCU, i);
++ }
++
+ rsnd_mod_init(priv, &src->mod, ops, RSND_MOD_SRC, i);
-
-- dev_dbg(dev, "SCU%d probed\n", 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
++ }
++
++ return 0;
++}
--- 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,
+@@ -121,7 +121,7 @@ static int rsnd_ssi_master_clk_start(str
1, 2, 4, 8, 16, 6, 12,
};
unsigned int main_rate;
/*
* Find best clock, and try to start ADG
-@@ -287,7 +287,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
+@@ -287,7 +287,7 @@ static int rsnd_ssi_init(struct rsnd_mod
ssi->cr_own = cr;
ssi->err = -1; /* ignore 1st error */
return 0;
}
-@@ -387,7 +387,7 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
+@@ -387,7 +387,7 @@ static int rsnd_ssi_pio_start(struct rsn
/* enable PIO IRQ */
ssi->cr_etc = UIEN | OIEN | DIEN;
rsnd_ssi_hw_start(ssi, rdai, io);
---
-2.1.2
-