Commit 186fadc1 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: rsnd: add TDM Extend Mode support

Renesas R-Car can out TDM by
1) 6ch x 1 DAI as TDM Extend Mode
2) 2ch x 4 x 1 DAI as TDM split Mode
3) 2ch x 3 DAI or
   2ch x 4 DAI as TDM Multichannel Mode

This patch adds 1) TDM Extend Mode. Because of HW design,
this 6ch data will be outputed via 8ch data width.
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 42ab9a79
...@@ -247,9 +247,9 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ...@@ -247,9 +247,9 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io) u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
{ {
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
u32 chan = runtime->channels; struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
u32 chan = rsnd_get_slot_rdai(rdai);
switch (chan) { switch (chan) {
case 1: case 1:
...@@ -569,9 +569,31 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ...@@ -569,9 +569,31 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0; return 0;
} }
static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
u32 tx_mask, u32 rx_mask,
int slots, int slot_width)
{
struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct device *dev = rsnd_priv_to_dev(priv);
switch (slots) {
case 6:
/* TDM Extend Mode */
rdai->slots = slots;
break;
default:
dev_err(dev, "unsupported TDM slots (%d)\n", slots);
return -EINVAL;
}
return 0;
}
static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
.trigger = rsnd_soc_dai_trigger, .trigger = rsnd_soc_dai_trigger,
.set_fmt = rsnd_soc_dai_set_fmt, .set_fmt = rsnd_soc_dai_set_fmt,
.set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
}; };
static int rsnd_dai_probe(struct rsnd_priv *priv) static int rsnd_dai_probe(struct rsnd_priv *priv)
...@@ -626,7 +648,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) ...@@ -626,7 +648,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
drv->playback.rates = RSND_RATES; drv->playback.rates = RSND_RATES;
drv->playback.formats = RSND_FMTS; drv->playback.formats = RSND_FMTS;
drv->playback.channels_min = 2; drv->playback.channels_min = 2;
drv->playback.channels_max = 2; drv->playback.channels_max = 6;
drv->playback.stream_name = rdai->playback.name; drv->playback.stream_name = rdai->playback.name;
snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE, snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE,
...@@ -634,7 +656,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) ...@@ -634,7 +656,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
drv->capture.rates = RSND_RATES; drv->capture.rates = RSND_RATES;
drv->capture.formats = RSND_FMTS; drv->capture.formats = RSND_FMTS;
drv->capture.channels_min = 2; drv->capture.channels_min = 2;
drv->capture.channels_max = 2; drv->capture.channels_max = 6;
drv->capture.stream_name = rdai->capture.name; drv->capture.stream_name = rdai->capture.name;
rdai->playback.rdai = rdai; rdai->playback.rdai = rdai;
......
...@@ -230,6 +230,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) ...@@ -230,6 +230,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80),
RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80),
RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8, 0x80), RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8, 0x80),
RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80),
RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
}; };
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
*/ */
enum rsnd_reg { enum rsnd_reg {
/* SCU (SRC/SSIU/MIX/CTU/DVC) */ /* SCU (SRC/SSIU/MIX/CTU/DVC) */
RSND_REG_SSI_MODE, /* Gen2 only */
RSND_REG_SSI_MODE0, RSND_REG_SSI_MODE0,
RSND_REG_SSI_MODE1, RSND_REG_SSI_MODE1,
RSND_REG_SSI_CTRL, /* Gen2 only */ RSND_REG_SSI_CTRL, /* Gen2 only */
......
...@@ -24,7 +24,9 @@ ...@@ -24,7 +24,9 @@
#define OIEN (1 << 26) /* Overflow Interrupt Enable */ #define OIEN (1 << 26) /* Overflow Interrupt Enable */
#define IIEN (1 << 25) /* Idle Mode Interrupt Enable */ #define IIEN (1 << 25) /* Idle Mode Interrupt Enable */
#define DIEN (1 << 24) /* Data Interrupt Enable */ #define DIEN (1 << 24) /* Data Interrupt Enable */
#define CHNL_4 (1 << 22) /* Channels */
#define CHNL_6 (2 << 22) /* Channels */
#define CHNL_8 (3 << 22) /* Channels */
#define DWL_8 (0 << 19) /* Data Word Length */ #define DWL_8 (0 << 19) /* Data Word Length */
#define DWL_16 (1 << 19) /* Data Word Length */ #define DWL_16 (1 << 19) /* Data Word Length */
#define DWL_18 (2 << 19) /* Data Word Length */ #define DWL_18 (2 << 19) /* Data Word Length */
...@@ -57,6 +59,7 @@ ...@@ -57,6 +59,7 @@
* SSIWSR * SSIWSR
*/ */
#define CONT (1 << 8) /* WS Continue Function */ #define CONT (1 << 8) /* WS Continue Function */
#define WS_MODE (1 << 0) /* WS Mode */
#define SSI_NAME "ssi" #define SSI_NAME "ssi"
...@@ -261,6 +264,7 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi, ...@@ -261,6 +264,7 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi,
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
u32 cr_own; u32 cr_own;
u32 cr_mode; u32 cr_mode;
u32 wsr;
/* /*
* always use 32bit system word. * always use 32bit system word.
...@@ -297,8 +301,20 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi, ...@@ -297,8 +301,20 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi,
cr_mode = DIEN; /* PIO : enable Data interrupt */ cr_mode = DIEN; /* PIO : enable Data interrupt */
} }
/*
* TDM Extend Mode
* see
* rsnd_ssiu_init_gen2()
*/
wsr = ssi->wsr;
if (rsnd_get_slot_runtime(io) >= 6) {
wsr |= WS_MODE;
cr_own |= CHNL_8;
}
ssi->cr_own = cr_own; ssi->cr_own = cr_own;
ssi->cr_mode = cr_mode; ssi->cr_mode = cr_mode;
ssi->wsr = wsr;
return 0; return 0;
} }
......
...@@ -78,6 +78,15 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, ...@@ -78,6 +78,15 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (rsnd_get_slot_runtime(io) >= 6) {
/*
* TDM Extend Mode
* see
* rsnd_ssi_config_init()
*/
rsnd_mod_write(mod, SSI_MODE, 0x1);
}
if (rsnd_ssi_use_busif(io)) { if (rsnd_ssi_use_busif(io)) {
u32 val = rsnd_get_dalign(mod, io); u32 val = rsnd_get_dalign(mod, io);
......
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