Commit ae5c3223 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: add Renesas R-Car SSI feature

Renesas R-Car series sound circuit consists of SSI and its peripheral.
But this peripheral circuit is different between
R-Car Generation1 (E1/M1/H1) and Generation2 (E2/M2/H2)
(Actually, there are many difference in Generation1 chips)

As 1st protype, this patch adds SSI feature on this driver.
But, it is PIO sound playback support only at this point.
The DMA transfer, and capture feature will be supported in the future
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent dfc9403b
...@@ -16,11 +16,30 @@ ...@@ -16,11 +16,30 @@
#define RSND_GEN1_SRU 0 #define RSND_GEN1_SRU 0
#define RSND_GEN1_ADG 1 #define RSND_GEN1_ADG 1
#define RSND_GEN1_SSI 2
#define RSND_GEN2_SRU 0 #define RSND_GEN2_SRU 0
#define RSND_GEN2_ADG 1 #define RSND_GEN2_ADG 1
#define RSND_GEN2_SSIU 2
#define RSND_GEN2_SSI 3
#define RSND_BASE_MAX 2 #define RSND_BASE_MAX 4
/*
* flags
*
* 0xA0000000
*
* A : clock sharing settings
*/
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
#define RSND_SSI_CLK_FROM_ADG (1 << 30) /* clock parent is master */
#define RSND_SSI_SYNC (1 << 29) /* SSI34_sync etc */
struct rsnd_ssi_platform_info {
int pio_irq;
u32 flags;
};
struct rsnd_scu_platform_info { struct rsnd_scu_platform_info {
u32 flags; u32 flags;
...@@ -43,6 +62,8 @@ struct rsnd_dai_platform_info { ...@@ -43,6 +62,8 @@ struct rsnd_dai_platform_info {
struct rcar_snd_info { struct rcar_snd_info {
u32 flags; u32 flags;
struct rsnd_ssi_platform_info *ssi_info;
int ssi_info_nr;
struct rsnd_scu_platform_info *scu_info; struct rsnd_scu_platform_info *scu_info;
int scu_info_nr; int scu_info_nr;
struct rsnd_dai_platform_info *dai_info; struct rsnd_dai_platform_info *dai_info;
......
snd-soc-rcar-objs := core.o gen.o scu.o adg.o snd-soc-rcar-objs := core.o gen.o scu.o adg.o ssi.o
obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
\ No newline at end of file
...@@ -639,6 +639,10 @@ static int rsnd_probe(struct platform_device *pdev) ...@@ -639,6 +639,10 @@ static int rsnd_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = rsnd_ssi_probe(pdev, info, priv);
if (ret < 0)
return ret;
/* /*
* asoc register * asoc register
*/ */
...@@ -677,6 +681,7 @@ static int rsnd_remove(struct platform_device *pdev) ...@@ -677,6 +681,7 @@ static int rsnd_remove(struct platform_device *pdev)
/* /*
* remove each module * remove each module
*/ */
rsnd_ssi_remove(pdev, priv);
rsnd_adg_remove(pdev, priv); rsnd_adg_remove(pdev, priv);
rsnd_scu_remove(pdev, priv); rsnd_scu_remove(pdev, priv);
rsnd_dai_remove(pdev, priv); rsnd_dai_remove(pdev, priv);
......
...@@ -72,6 +72,12 @@ static int rsnd_gen1_path_init(struct rsnd_priv *priv, ...@@ -72,6 +72,12 @@ static int rsnd_gen1_path_init(struct rsnd_priv *priv,
else else
id = info->ssi_id_capture; id = info->ssi_id_capture;
/* SSI */
mod = rsnd_ssi_mod_get(priv, id);
ret = rsnd_dai_connect(rdai, mod, io);
if (ret < 0)
return ret;
/* SCU */ /* SCU */
mod = rsnd_scu_mod_get(priv, id); mod = rsnd_scu_mod_get(priv, id);
ret = rsnd_dai_connect(rdai, mod, io); ret = rsnd_dai_connect(rdai, mod, io);
...@@ -120,6 +126,12 @@ static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen) ...@@ -120,6 +126,12 @@ static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18); RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18);
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c); RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c);
RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20); RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20);
RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00);
RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04);
RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08);
RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c);
RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20);
} }
static int rsnd_gen1_probe(struct platform_device *pdev, static int rsnd_gen1_probe(struct platform_device *pdev,
...@@ -130,14 +142,17 @@ static int rsnd_gen1_probe(struct platform_device *pdev, ...@@ -130,14 +142,17 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
struct rsnd_gen *gen = rsnd_priv_to_gen(priv); struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
struct resource *sru_res; struct resource *sru_res;
struct resource *adg_res; struct resource *adg_res;
struct resource *ssi_res;
/* /*
* map address * map address
*/ */
sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU); sru_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU);
adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG); adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG);
ssi_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI);
if (!sru_res || if (!sru_res ||
!adg_res) { !adg_res ||
!ssi_res) {
dev_err(dev, "Not enough SRU/SSI/ADG platform resources.\n"); dev_err(dev, "Not enough SRU/SSI/ADG platform resources.\n");
return -ENODEV; return -ENODEV;
} }
...@@ -146,8 +161,10 @@ static int rsnd_gen1_probe(struct platform_device *pdev, ...@@ -146,8 +161,10 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res); gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res);
gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res); gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res);
gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res);
if (!gen->base[RSND_GEN1_SRU] || if (!gen->base[RSND_GEN1_SRU] ||
!gen->base[RSND_GEN1_ADG]) { !gen->base[RSND_GEN1_ADG] ||
!gen->base[RSND_GEN1_SSI]) {
dev_err(dev, "SRU/SSI/ADG ioremap failed\n"); dev_err(dev, "SRU/SSI/ADG ioremap failed\n");
return -ENODEV; return -ENODEV;
} }
...@@ -159,8 +176,11 @@ static int rsnd_gen1_probe(struct platform_device *pdev, ...@@ -159,8 +176,11 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
gen->base[RSND_GEN1_SRU]); gen->base[RSND_GEN1_SRU]);
dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start, dev_dbg(dev, "ADG : %08x => %p\n", adg_res->start,
gen->base[RSND_GEN1_ADG]); gen->base[RSND_GEN1_ADG]);
dev_dbg(dev, "SSI : %08x => %p\n", ssi_res->start,
gen->base[RSND_GEN1_SSI]);
return 0; return 0;
} }
static void rsnd_gen1_remove(struct platform_device *pdev, static void rsnd_gen1_remove(struct platform_device *pdev,
......
...@@ -43,6 +43,13 @@ enum rsnd_reg { ...@@ -43,6 +43,13 @@ enum rsnd_reg {
RSND_REG_AUDIO_CLK_SEL4, RSND_REG_AUDIO_CLK_SEL4,
RSND_REG_AUDIO_CLK_SEL5, RSND_REG_AUDIO_CLK_SEL5,
/* SSI */
RSND_REG_SSICR,
RSND_REG_SSISR,
RSND_REG_SSITDR,
RSND_REG_SSIRDR,
RSND_REG_SSIWSR,
RSND_REG_MAX, RSND_REG_MAX,
}; };
...@@ -151,6 +158,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod, ...@@ -151,6 +158,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod,
struct rsnd_dai_stream *io); struct rsnd_dai_stream *io);
int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io); int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
#define rsnd_dai_get_platform_info(rdai) ((rdai)->info) #define rsnd_dai_get_platform_info(rdai) ((rdai)->info)
#define rsnd_io_to_runtime(io) ((io)->substream->runtime)
void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
...@@ -209,6 +217,11 @@ struct rsnd_priv { ...@@ -209,6 +217,11 @@ struct rsnd_priv {
*/ */
void *adg; void *adg;
/*
* below value will be filled on rsnd_ssi_probe()
*/
void *ssiu;
/* /*
* below value will be filled on rsnd_dai_probe() * below value will be filled on rsnd_dai_probe()
*/ */
...@@ -232,4 +245,14 @@ void rsnd_scu_remove(struct platform_device *pdev, ...@@ -232,4 +245,14 @@ void rsnd_scu_remove(struct platform_device *pdev,
struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id); struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
#define rsnd_scu_nr(priv) ((priv)->scu_nr) #define rsnd_scu_nr(priv) ((priv)->scu_nr)
/*
* R-Car SSI
*/
int rsnd_ssi_probe(struct platform_device *pdev,
struct rcar_snd_info *info,
struct rsnd_priv *priv);
void rsnd_ssi_remove(struct platform_device *pdev,
struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
#endif #endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment