From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 07:24:11 +0000
Subject: [PATCH] add stmac read mac form eeprom
---
kernel/sound/soc/sh/rcar/ssi.c | 551 ++++++++++++++++++++++++++++++++++---------------------
1 files changed, 340 insertions(+), 211 deletions(-)
diff --git a/kernel/sound/soc/sh/rcar/ssi.c b/kernel/sound/soc/sh/rcar/ssi.c
index a6cf2ac..2ead447 100644
--- a/kernel/sound/soc/sh/rcar/ssi.c
+++ b/kernel/sound/soc/sh/rcar/ssi.c
@@ -42,7 +42,13 @@
#define DWL_24 (5 << 19) /* Data Word Length */
#define DWL_32 (6 << 19) /* Data Word Length */
+/*
+ * System word length
+ */
+#define SWL_16 (1 << 16) /* R/W System Word Length */
+#define SWL_24 (2 << 16) /* R/W System Word Length */
#define SWL_32 (3 << 16) /* R/W System Word Length */
+
#define SCKD (1 << 15) /* Serial Bit Clock Direction */
#define SWSD (1 << 14) /* Serial WS Direction */
#define SCKP (1 << 13) /* Serial Bit Clock Polarity */
@@ -93,9 +99,7 @@
/* flags */
#define RSND_SSI_CLK_PIN_SHARE (1 << 0)
#define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
-#define RSND_SSI_HDMI0 (1 << 2) /* for HDMI0 */
-#define RSND_SSI_HDMI1 (1 << 3) /* for HDMI1 */
-#define RSND_SSI_PROBED (1 << 4)
+#define RSND_SSI_PROBED (1 << 2)
#define for_each_rsnd_ssi(pos, priv, i) \
for (i = 0; \
@@ -107,25 +111,13 @@
#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
#define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
-#define rsnd_ssi_is_multi_slave(mod, io) \
- (rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod)))
+#define rsnd_ssi_is_multi_secondary(mod, io) \
+ (rsnd_ssi_multi_secondaries(io) & (1 << rsnd_mod_id(mod)))
#define rsnd_ssi_is_run_mods(mod, io) \
(rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
#define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod))
-int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io)
-{
- struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
- if (rsnd_flags_has(ssi, RSND_SSI_HDMI0))
- return RSND_SSI_HDMI_PORT0;
-
- if (rsnd_flags_has(ssi, RSND_SSI_HDMI1))
- return RSND_SSI_HDMI_PORT1;
-
- return 0;
-}
+static int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
{
@@ -170,11 +162,10 @@
udelay(5);
}
- dev_warn(dev, "%s[%d] status check failed\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
+ dev_warn(dev, "%s status check failed\n", rsnd_mod_name(mod));
}
-static u32 rsnd_ssi_multi_slaves(struct rsnd_dai_stream *io)
+static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
{
struct rsnd_mod *mod;
enum rsnd_mod_type types[] = {
@@ -202,7 +193,7 @@
struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
u32 mods;
- mods = rsnd_ssi_multi_slaves_runtime(io) |
+ mods = rsnd_ssi_multi_secondaries_runtime(io) |
1 << rsnd_mod_id(ssi_mod);
if (ssi_parent_mod)
@@ -211,22 +202,40 @@
return mods;
}
-u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io)
+u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io)
{
- if (rsnd_runtime_is_ssi_multi(io))
- return rsnd_ssi_multi_slaves(io);
+ if (rsnd_runtime_is_multi_ssi(io))
+ return rsnd_ssi_multi_secondaries(io);
return 0;
}
-unsigned int rsnd_ssi_clk_query(struct rsnd_priv *priv,
+static u32 rsnd_rdai_width_to_swl(struct rsnd_dai *rdai)
+{
+ struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
+ struct device *dev = rsnd_priv_to_dev(priv);
+ int width = rsnd_rdai_width_get(rdai);
+
+ switch (width) {
+ case 32: return SWL_32;
+ case 24: return SWL_24;
+ case 16: return SWL_16;
+ }
+
+ dev_err(dev, "unsupported slot width value: %d\n", width);
+ return 0;
+}
+
+unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai,
int param1, int param2, int *idx)
{
+ struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
int ssi_clk_mul_table[] = {
1, 2, 4, 8, 16, 6, 12,
};
int j, ret;
unsigned int main_rate;
+ int width = rsnd_rdai_width_get(rdai);
for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
@@ -239,12 +248,7 @@
if (j == 0)
continue;
- /*
- * this driver is assuming that
- * system word is 32bit x chan
- * see rsnd_ssi_init()
- */
- main_rate = 32 * param1 * param2 * ssi_clk_mul_table[j];
+ main_rate = width * param1 * param2 * ssi_clk_mul_table[j];
ret = rsnd_adg_clk_query(priv, main_rate);
if (ret < 0)
@@ -279,8 +283,13 @@
if (!rsnd_ssi_can_output_clk(mod))
return 0;
- if (rsnd_ssi_is_multi_slave(mod, io))
+ if (rsnd_ssi_is_multi_secondary(mod, io))
return 0;
+
+ if (rsnd_runtime_is_tdm_split(io))
+ chan = rsnd_io_converted_chan(io);
+
+ chan = rsnd_channel_normalization(chan);
if (ssi->usrcnt > 0) {
if (ssi->rate != rate) {
@@ -288,10 +297,15 @@
return -EINVAL;
}
+ if (ssi->chan != chan) {
+ dev_err(dev, "SSI parent/child should use same chan\n");
+ return -EINVAL;
+ }
+
return 0;
}
- main_rate = rsnd_ssi_clk_query(priv, rate, chan, &idx);
+ main_rate = rsnd_ssi_clk_query(rdai, rate, chan, &idx);
if (!main_rate) {
dev_err(dev, "unsupported clock rate\n");
return -EIO;
@@ -311,13 +325,14 @@
* SSICR : FORCE, SCKD, SWSD
* SSIWSR : CONT
*/
- ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx);
+ ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) |
+ SCKD | SWSD | CKDV(idx);
ssi->wsr = CONT;
ssi->rate = rate;
+ ssi->chan = chan;
- dev_dbg(dev, "%s[%d] outputs %u Hz\n",
- rsnd_mod_name(mod),
- rsnd_mod_id(mod), rate);
+ dev_dbg(dev, "%s outputs %d chan %u Hz\n",
+ rsnd_mod_name(mod), chan, rate);
return 0;
}
@@ -339,6 +354,7 @@
ssi->cr_clk = 0;
ssi->rate = 0;
+ ssi->chan = 0;
rsnd_adg_ssi_clk_stop(mod);
}
@@ -347,29 +363,48 @@
struct rsnd_dai_stream *io)
{
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+ struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
+ struct device *dev = rsnd_priv_to_dev(priv);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
u32 cr_own = ssi->cr_own;
u32 cr_mode = ssi->cr_mode;
u32 wsr = ssi->wsr;
- int is_tdm;
+ int width;
+ int is_tdm, is_tdm_split;
+ int id = rsnd_mod_id(mod);
+ int i;
+ u32 sys_int_enable = 0;
- is_tdm = rsnd_runtime_is_ssi_tdm(io);
+ is_tdm = rsnd_runtime_is_tdm(io);
+ is_tdm_split = rsnd_runtime_is_tdm_split(io);
- /*
- * always use 32bit system word.
- * see also rsnd_ssi_master_clk_enable()
- */
- cr_own |= FORCE | SWL_32;
+ if (is_tdm)
+ dev_dbg(dev, "TDM mode\n");
+ if (is_tdm_split)
+ dev_dbg(dev, "TDM Split mode\n");
+
+ cr_own |= FORCE | rsnd_rdai_width_to_swl(rdai);
if (rdai->bit_clk_inv)
cr_own |= SCKP;
- if (rdai->frm_clk_inv ^ is_tdm)
+ if (rdai->frm_clk_inv && !is_tdm)
cr_own |= SWSP;
if (rdai->data_alignment)
cr_own |= SDTA;
if (rdai->sys_delay)
cr_own |= DEL;
+
+ /*
+ * TDM Mode
+ * see
+ * rsnd_ssiu_init_gen2()
+ */
+ wsr = ssi->wsr;
+ if (is_tdm || is_tdm_split) {
+ wsr |= WS_MODE;
+ cr_own |= CHNL_8;
+ }
/*
* We shouldn't exchange SWSP after running.
@@ -382,12 +417,29 @@
cr_own |= TRMD;
cr_own &= ~DWL_MASK;
- switch (snd_pcm_format_width(runtime->format)) {
+ width = snd_pcm_format_width(runtime->format);
+ if (is_tdm_split) {
+ /*
+ * The SWL and DWL bits in SSICR should be fixed at 32-bit
+ * setting when TDM split mode.
+ * see datasheet
+ * Operation :: TDM Format Split Function (TDM Split Mode)
+ */
+ width = 32;
+ }
+
+ switch (width) {
+ case 8:
+ cr_own |= DWL_8;
+ break;
case 16:
cr_own |= DWL_16;
break;
case 24:
cr_own |= DWL_24;
+ break;
+ case 32:
+ cr_own |= DWL_32;
break;
}
@@ -398,16 +450,38 @@
cr_mode = DIEN; /* PIO : enable Data interrupt */
}
- /*
- * TDM Extend Mode
- * see
- * rsnd_ssiu_init_gen2()
- */
- wsr = ssi->wsr;
- if (is_tdm) {
- wsr |= WS_MODE;
- cr_own |= CHNL_8;
+ /* enable busif buffer over/under run interrupt. */
+ if (is_tdm || is_tdm_split) {
+ switch (id) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ for (i = 0; i < 4; i++) {
+ sys_int_enable = rsnd_mod_read(mod,
+ SSI_SYS_INT_ENABLE(i * 2));
+ sys_int_enable |= 0xf << (id * 4);
+ rsnd_mod_write(mod,
+ SSI_SYS_INT_ENABLE(i * 2),
+ sys_int_enable);
+ }
+
+ break;
+ case 9:
+ for (i = 0; i < 4; i++) {
+ sys_int_enable = rsnd_mod_read(mod,
+ SSI_SYS_INT_ENABLE((i * 2) + 1));
+ sys_int_enable |= 0xf << 4;
+ rsnd_mod_write(mod,
+ SSI_SYS_INT_ENABLE((i * 2) + 1),
+ sys_int_enable);
+ }
+
+ break;
+ }
}
+
init_end:
ssi->cr_own = cr_own;
ssi->cr_mode = cr_mode;
@@ -433,13 +507,20 @@
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+ int ret;
if (!rsnd_ssi_is_run_mods(mod, io))
return 0;
+ ret = rsnd_ssi_master_clk_start(mod, io);
+ if (ret < 0)
+ return ret;
+
ssi->usrcnt++;
- rsnd_mod_power_on(mod);
+ ret = rsnd_mod_power_on(mod);
+ if (ret < 0)
+ return ret;
rsnd_ssi_config_init(mod, io);
@@ -457,13 +538,19 @@
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct device *dev = rsnd_priv_to_dev(priv);
+ int is_tdm, is_tdm_split;
+ int id = rsnd_mod_id(mod);
+ int i;
+ u32 sys_int_enable = 0;
+
+ is_tdm = rsnd_runtime_is_tdm(io);
+ is_tdm_split = rsnd_runtime_is_tdm_split(io);
if (!rsnd_ssi_is_run_mods(mod, io))
return 0;
if (!ssi->usrcnt) {
- dev_err(dev, "%s[%d] usrcnt error\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
+ dev_err(dev, "%s usrcnt error\n", rsnd_mod_name(mod));
return -EIO;
}
@@ -479,6 +566,38 @@
ssi->wsr = 0;
}
+ /* disable busif buffer over/under run interrupt. */
+ if (is_tdm || is_tdm_split) {
+ switch (id) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ for (i = 0; i < 4; i++) {
+ sys_int_enable = rsnd_mod_read(mod,
+ SSI_SYS_INT_ENABLE(i * 2));
+ sys_int_enable &= ~(0xf << (id * 4));
+ rsnd_mod_write(mod,
+ SSI_SYS_INT_ENABLE(i * 2),
+ sys_int_enable);
+ }
+
+ break;
+ case 9:
+ for (i = 0; i < 4; i++) {
+ sys_int_enable = rsnd_mod_read(mod,
+ SSI_SYS_INT_ENABLE((i * 2) + 1));
+ sys_int_enable &= ~(0xf << 4);
+ rsnd_mod_write(mod,
+ SSI_SYS_INT_ENABLE((i * 2) + 1),
+ sys_int_enable);
+ }
+
+ break;
+ }
+ }
+
return 0;
}
@@ -487,26 +606,16 @@
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int chan = params_channels(params);
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+ unsigned int fmt_width = snd_pcm_format_width(params_format(params));
- /*
- * snd_pcm_ops::hw_params will be called *before*
- * snd_soc_dai_ops::trigger. Thus, ssi->usrcnt is 0
- * in 1st call.
- */
- if (ssi->usrcnt) {
- /*
- * Already working.
- * It will happen if SSI has parent/child connection.
- * it is error if child <-> parent SSI uses
- * different channels.
- */
- if (ssi->chan != chan)
- return -EIO;
+ if (fmt_width > rdai->chan_width) {
+ struct rsnd_priv *priv = rsnd_io_to_priv(io);
+ struct device *dev = rsnd_priv_to_dev(priv);
+
+ dev_err(dev, "invalid combination of slot-width and format-data-width\n");
+ return -EINVAL;
}
-
- ssi->chan = chan;
return 0;
}
@@ -524,7 +633,7 @@
* EN will be set via SSIU :: SSI_CONTROL
* if Multi channel mode
*/
- if (rsnd_ssi_multi_slaves_runtime(io))
+ if (rsnd_ssi_multi_secondaries_runtime(io))
return 0;
/*
@@ -573,7 +682,7 @@
/* In multi-SSI mode, stop is performed by setting ssi0129 in
* SSI_CONTROL to 0 (in rsnd_ssio_stop_gen2). Do nothing here.
*/
- if (rsnd_ssi_multi_slaves_runtime(io))
+ if (rsnd_ssi_multi_secondaries_runtime(io))
return 0;
/*
@@ -594,6 +703,11 @@
int enable)
{
u32 val = 0;
+ int is_tdm, is_tdm_split;
+ int id = rsnd_mod_id(mod);
+
+ is_tdm = rsnd_runtime_is_tdm(io);
+ is_tdm_split = rsnd_runtime_is_tdm_split(io);
if (rsnd_is_gen1(priv))
return 0;
@@ -606,6 +720,19 @@
if (enable)
val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000;
+
+ if (is_tdm || is_tdm_split) {
+ switch (id) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 9:
+ val |= 0x0000ff00;
+ break;
+ }
+ }
rsnd_mod_write(mod, SSI_INT_ENABLE, val);
@@ -623,6 +750,12 @@
u32 status;
bool elapsed = false;
bool stop = false;
+ int id = rsnd_mod_id(mod);
+ int i;
+ int is_tdm, is_tdm_split;
+
+ is_tdm = rsnd_runtime_is_tdm(io);
+ is_tdm_split = rsnd_runtime_is_tdm_split(io);
spin_lock(&priv->lock);
@@ -638,10 +771,55 @@
/* DMA only */
if (is_dma && (status & (UIRQ | OIRQ))) {
- rsnd_dbg_irq_status(dev, "%s[%d] err status : 0x%08x\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod), status);
+ rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n",
+ rsnd_mod_name(mod), status);
stop = true;
+ }
+
+ status = 0;
+
+ if (is_tdm || is_tdm_split) {
+ switch (id) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ for (i = 0; i < 4; i++) {
+ status = rsnd_mod_read(mod,
+ SSI_SYS_STATUS(i * 2));
+ status &= 0xf << (id * 4);
+
+ if (status) {
+ rsnd_dbg_irq_status(dev,
+ "%s err status : 0x%08x\n",
+ rsnd_mod_name(mod), status);
+ rsnd_mod_write(mod,
+ SSI_SYS_STATUS(i * 2),
+ 0xf << (id * 4));
+ stop = true;
+ }
+ }
+ break;
+ case 9:
+ for (i = 0; i < 4; i++) {
+ status = rsnd_mod_read(mod,
+ SSI_SYS_STATUS((i * 2) + 1));
+ status &= 0xf << 4;
+
+ if (status) {
+ rsnd_dbg_irq_status(dev,
+ "%s err status : 0x%08x\n",
+ rsnd_mod_name(mod), status);
+ rsnd_mod_write(mod,
+ SSI_SYS_STATUS((i * 2) + 1),
+ 0xf << 4);
+ stop = true;
+ }
+ }
+ break;
+ }
}
rsnd_ssi_status_clear(mod);
@@ -665,6 +843,41 @@
return IRQ_HANDLED;
}
+static u32 *rsnd_ssi_get_status(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ enum rsnd_mod_type type)
+{
+ /*
+ * SSIP (= SSI parent) needs to be special, otherwise,
+ * 2nd SSI might doesn't start. see also rsnd_mod_call()
+ *
+ * We can't include parent SSI status on SSI, because we don't know
+ * how many SSI requests parent SSI. Thus, it is localed on "io" now.
+ * ex) trouble case
+ * Playback: SSI0
+ * Capture : SSI1 (needs SSI0)
+ *
+ * 1) start Capture -> SSI0/SSI1 are started.
+ * 2) start Playback -> SSI0 doesn't work, because it is already
+ * marked as "started" on 1)
+ *
+ * OTOH, using each mod's status is good for MUX case.
+ * It doesn't need to start in 2nd start
+ * ex)
+ * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
+ * |
+ * IO-1: SRC1 -> CTU2 -+
+ *
+ * 1) start IO-0 -> start SSI0
+ * 2) start IO-1 -> SSI0 doesn't need to start, because it is
+ * already started on 1)
+ */
+ if (type == RSND_MOD_SSIP)
+ return &io->parent_ssi_status;
+
+ return rsnd_mod_get_status(mod, io, type);
+}
+
/*
* SSI PIO
*/
@@ -680,12 +893,13 @@
if (!rsnd_rdai_is_clk_master(rdai))
return;
- if (rsnd_ssi_is_multi_slave(mod, io))
+ if (rsnd_ssi_is_multi_secondary(mod, io))
return;
switch (rsnd_mod_id(mod)) {
case 1:
case 2:
+ case 9:
rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP);
break;
case 4:
@@ -717,23 +931,19 @@
{
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- int ret;
+ int ret = 0;
/*
* SSIP/SSIU/IRQ are not needed on
- * SSI Multi slaves
+ * SSI Multi secondaries
*/
- if (rsnd_ssi_is_multi_slave(mod, io))
+ if (rsnd_ssi_is_multi_secondary(mod, io))
return 0;
/*
* It can't judge ssi parent at this point
* see rsnd_ssi_pcm_new()
*/
-
- ret = rsnd_ssiu_attach(io, mod);
- if (ret < 0)
- return ret;
/*
* SSI might be called again as PIO fallback
@@ -855,26 +1065,19 @@
return 0;
}
-static int rsnd_ssi_prepare(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_ssi_master_clk_start(mod, io);
-}
-
static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
- .name = SSI_NAME,
- .probe = rsnd_ssi_common_probe,
- .remove = rsnd_ssi_common_remove,
- .init = rsnd_ssi_pio_init,
- .quit = rsnd_ssi_quit,
- .start = rsnd_ssi_start,
- .stop = rsnd_ssi_stop,
- .irq = rsnd_ssi_irq,
- .pointer = rsnd_ssi_pio_pointer,
- .pcm_new = rsnd_ssi_pcm_new,
- .hw_params = rsnd_ssi_hw_params,
- .prepare = rsnd_ssi_prepare,
+ .name = SSI_NAME,
+ .probe = rsnd_ssi_common_probe,
+ .remove = rsnd_ssi_common_remove,
+ .init = rsnd_ssi_pio_init,
+ .quit = rsnd_ssi_quit,
+ .start = rsnd_ssi_start,
+ .stop = rsnd_ssi_stop,
+ .irq = rsnd_ssi_irq,
+ .pointer = rsnd_ssi_pio_pointer,
+ .pcm_new = rsnd_ssi_pcm_new,
+ .hw_params = rsnd_ssi_hw_params,
+ .get_status = rsnd_ssi_get_status,
};
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
@@ -885,9 +1088,9 @@
/*
* SSIP/SSIU/IRQ/DMA are not needed on
- * SSI Multi slaves
+ * SSI Multi secondaries
*/
- if (rsnd_ssi_is_multi_slave(mod, io))
+ if (rsnd_ssi_is_multi_secondary(mod, io))
return 0;
ret = rsnd_ssi_common_probe(mod, io, priv);
@@ -915,8 +1118,7 @@
*/
mod->ops = &rsnd_ssi_pio_ops;
- dev_info(dev, "%s[%d] fallback to PIO mode\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
+ dev_info(dev, "%s fallback to PIO mode\n", rsnd_mod_name(mod));
return 0;
}
@@ -928,6 +1130,17 @@
int is_play = rsnd_io_is_play(io);
char *name;
+ /*
+ * It should use "rcar_sound,ssiu" on DT.
+ * But, we need to keep compatibility for old version.
+ *
+ * If it has "rcar_sound.ssiu", it will be used.
+ * If not, "rcar_sound.ssi" will be used.
+ * see
+ * rsnd_ssiu_dma_req()
+ * rsnd_dma_of_path()
+ */
+
if (rsnd_ssi_use_busif(io))
name = is_play ? "rxu" : "txu";
else
@@ -938,26 +1151,25 @@
}
static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
- .name = SSI_NAME,
- .dma_req = rsnd_ssi_dma_req,
- .probe = rsnd_ssi_dma_probe,
- .remove = rsnd_ssi_common_remove,
- .init = rsnd_ssi_init,
- .quit = rsnd_ssi_quit,
- .start = rsnd_ssi_start,
- .stop = rsnd_ssi_stop,
- .irq = rsnd_ssi_irq,
- .pcm_new = rsnd_ssi_pcm_new,
- .fallback = rsnd_ssi_fallback,
- .hw_params = rsnd_ssi_hw_params,
- .prepare = rsnd_ssi_prepare,
+ .name = SSI_NAME,
+ .dma_req = rsnd_ssi_dma_req,
+ .probe = rsnd_ssi_dma_probe,
+ .remove = rsnd_ssi_common_remove,
+ .init = rsnd_ssi_init,
+ .quit = rsnd_ssi_quit,
+ .start = rsnd_ssi_start,
+ .stop = rsnd_ssi_stop,
+ .irq = rsnd_ssi_irq,
+ .pcm_new = rsnd_ssi_pcm_new,
+ .fallback = rsnd_ssi_fallback,
+ .hw_params = rsnd_ssi_hw_params,
+ .get_status = rsnd_ssi_get_status,
};
-int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
+static int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
{
return mod->ops == &rsnd_ssi_dma_ops;
}
-
/*
* ssi mod function
@@ -1014,54 +1226,6 @@
of_node_put(node);
}
-static void __rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
- struct rsnd_dai_stream *io,
- struct device_node *remote_ep)
-{
- struct device *dev = rsnd_priv_to_dev(priv);
- struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_ssi *ssi;
- struct device_node *remote_node = of_graph_get_port_parent(remote_ep);
-
- /* support Gen3 only */
- if (!rsnd_is_gen3(priv))
- return;
-
- if (!mod)
- return;
-
- ssi = rsnd_mod_to_ssi(mod);
-
- /* HDMI0 */
- if (strstr(remote_node->full_name, "hdmi@fead0000")) {
- rsnd_flags_set(ssi, RSND_SSI_HDMI0);
- dev_dbg(dev, "%s[%d] connected to HDMI0\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
- }
-
- /* HDMI1 */
- if (strstr(remote_node->full_name, "hdmi@feae0000")) {
- rsnd_flags_set(ssi, RSND_SSI_HDMI1);
- dev_dbg(dev, "%s[%d] connected to HDMI1\n",
- rsnd_mod_name(mod), rsnd_mod_id(mod));
- }
-}
-
-void rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
- struct device_node *endpoint,
- int dai_i)
-{
- struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i);
- struct device_node *remote_ep;
-
- remote_ep = of_graph_get_remote_endpoint(endpoint);
- if (!remote_ep)
- return;
-
- __rsnd_ssi_parse_hdmi_connection(priv, &rdai->playback, remote_ep);
- __rsnd_ssi_parse_hdmi_connection(priv, &rdai->capture, remote_ep);
-}
-
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
{
if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
@@ -1076,41 +1240,6 @@
return 0;
return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
-}
-
-static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,
- struct rsnd_mod *mod,
- enum rsnd_mod_type type)
-{
- /*
- * SSIP (= SSI parent) needs to be special, otherwise,
- * 2nd SSI might doesn't start. see also rsnd_mod_call()
- *
- * We can't include parent SSI status on SSI, because we don't know
- * how many SSI requests parent SSI. Thus, it is localed on "io" now.
- * ex) trouble case
- * Playback: SSI0
- * Capture : SSI1 (needs SSI0)
- *
- * 1) start Capture -> SSI0/SSI1 are started.
- * 2) start Playback -> SSI0 doesn't work, because it is already
- * marked as "started" on 1)
- *
- * OTOH, using each mod's status is good for MUX case.
- * It doesn't need to start in 2nd start
- * ex)
- * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
- * |
- * IO-1: SRC1 -> CTU2 -+
- *
- * 1) start IO-0 -> start SSI0
- * 2) start IO-1 -> SSI0 doesn't need to start, because it is
- * already started on 1)
- */
- if (type == RSND_MOD_SSIP)
- return &io->parent_ssi_status;
-
- return rsnd_mod_get_status(io, mod, type);
}
int rsnd_ssi_probe(struct rsnd_priv *priv)
@@ -1179,7 +1308,7 @@
ops = &rsnd_ssi_dma_ops;
ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
- rsnd_ssi_get_status, RSND_MOD_SSI, i);
+ RSND_MOD_SSI, i);
if (ret) {
of_node_put(np);
goto rsnd_ssi_probe_done;
--
Gitblit v1.6.2