[alsa-devel] [PATCH 0/21] ASoC: rsnd: prepare for MIXer support
Hi Mark
These are prepare for MIXer support for Renesas sound card. Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> stream is no longer 1:1 relationship. this patch set don't use rsnd_mod_to_io() as prepare for MIXer support
1) - 2) bugfix patch for PIO mode. These are not critical bug since no platform is using PIO mode. 3) - 10) cleanup for DPCM related code for MIXer support 11) - 21) remove rsnd_mod_to_io() from Renesas sound driver
Kuninori Morimoto (21): 1) ASoC: rsnd: don't care under/over run error when PIO 2) ASoC: rsnd: don't call snd_pcm_period_elapsed() under spin lock 3) ASoC: rsrc-card: used "fe.xxx"/"be.xxx" name for dai_link 4) ASoC: rsrc-card: tidyup priv->snd_card setup timing 5) ASoC: rsrc-card: enable multi cpu/codec for DPCM 6) ASoC: rsrc-card: remove unused name 7) ASoC: rsnd-card: tidyup rsrc_priv_to_() 8) ASoC: rsrc-card: move rsrc_card_parse_daifmt() to upper side 9) ASoC: rsrc-card: tidyup return value of clock error 10) ASoC: rsrc-card: cleanup for DPCM 11) ASoC: rsnd: count each mod (SSI/SRC/DVC) 12) ASoC: rsnd: rsnd_mod has rsnd_priv 13) ASoC: rsnd: adds struct rsnd_dai_stream as on each fuction as parameter 14) ASoC: rsnd: add common interrupt handler for SSI/SRC/DMA 15) ASoC: rsnd: don't use rsnd_mod_to_io() on rsnd_get_adinr() 16) ASoC: rsnd: don't use rsnd_mod_to_io() on rsnd_dma_xxx() 17) ASoC: rsnd: don't use rsnd_mod_to_io() on rsnd_ssi_xxx() 18) ASoC: rsnd: don't use rsnd_mod_to_io() on rsnd_src_xxx() 19) ASoC: rsnd: don't use rsnd_mod_to_io() on snd_kcontrol 20) ASoC: rsnd: move rsnd_mod_is_working() to rsnd_io_is_working() 21) ASoC: rsnd: remove io from rsnd_mod
sound/soc/sh/rcar/core.c | 111 ++++++++++++++++++++++++--------- sound/soc/sh/rcar/dma.c | 113 ++++++++++++++++++++-------------- sound/soc/sh/rcar/dvc.c | 30 +++++---- sound/soc/sh/rcar/rsnd.h | 112 +++++++++++++++++++++------------ sound/soc/sh/rcar/rsrc-card.c | 438 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------- sound/soc/sh/rcar/src.c | 121 ++++++++++++++++++++---------------- sound/soc/sh/rcar/ssi.c | 96 +++++++++++++++++------------ 7 files changed, 558 insertions(+), 463 deletions(-)
Best regards --- Kuninori Morimoto
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
PIO is used only for checking data path / codec settings. And underrun is very normal when PIO mode. Let's don't care about under/over run error when PIO case. Otherwise, 1) too many HW restart happens, 2) some sounds which need much data transfer can't play since it falls into error detection method which was created for DMA transfer
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/ssi.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 50fa392..8569173 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -199,15 +199,17 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, } }
- cr_mode = rsnd_ssi_is_dma_mode(&ssi->mod) ? - DMEN : /* DMA : enable DMA */ - DIEN; /* PIO : enable Data interrupt */ - + if (rsnd_ssi_is_dma_mode(&ssi->mod)) { + cr_mode = UIEN | OIEN | /* over/under run */ + DMEN; /* DMA : enable DMA */ + } else { + cr_mode = DIEN; /* PIO : enable Data interrupt */ + }
cr = ssi->cr_own | ssi->cr_clk | cr_mode | - UIEN | OIEN | EN; + EN;
rsnd_mod_write(&ssi->mod, SSICR, cr);
@@ -452,8 +454,8 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) rsnd_dai_pointer_update(io, sizeof(*buf)); }
- /* PIO / DMA */ - if (status & (UIRQ | OIRQ)) { + /* DMA only */ + if (is_dma && (status & (UIRQ | OIRQ))) { struct device *dev = rsnd_priv_to_dev(priv);
/*
On Mon, Jun 15, 2015 at 06:20:54AM +0000, Kuninori Morimoto wrote:
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
PIO is used only for checking data path / codec settings. And underrun is very normal when PIO mode. Let's don't care about under/over run error when PIO case. Otherwise, 1) too many HW restart happens, 2) some sounds which need much data transfer can't play since it falls into error detection method which was created for DMA transfer
I've applied the whole series but I'm not thrilled with this one. I guess what you mean to say is that this is only used during bringup of a new platform in which case it's not that big a deal but otherwise then the usual thing with PIO is to implement FIQ support to keep the hardware full.
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
'a9e1ac1a9e4585b5("ASoC: rsnd: spin lock for interrupt handler")' added spin lock under interrupt handler to solve HW restart issue.
OTOH, current rsnd driver calls snd_pcm_period_elapsed() from rsnd_dai_pointer_update(). but, it will be called under spin lock if SSI was PIO mode.
If it was called under spin lock, it will call snd_pcm_update_state() -> snd_pcm_drain_done(). Then, it calls rsnd_soc_dai_trigger() and will be dead-lock. This patch doesn't call rsnd_dai_pointer_update() under spin lock
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 20 ++++++++++++++++++-- sound/soc/sh/rcar/dma.c | 11 ++++++++++- sound/soc/sh/rcar/rsnd.h | 3 ++- sound/soc/sh/rcar/ssi.c | 6 +++++- 4 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index d460d2a..027b043 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -302,7 +302,7 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional) return pos; }
-void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) +bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) { io->byte_pos += byte;
@@ -319,8 +319,24 @@ void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int byte) io->next_period_byte = io->byte_per_period; }
- snd_pcm_period_elapsed(substream); + return true; } + + return false; +} + +void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io) +{ + struct snd_pcm_substream *substream = io->substream; + + /* + * this function should be called... + * + * - if rsnd_dai_pointer_update() returns true + * - without spin lock + */ + + snd_pcm_period_elapsed(substream); }
static void rsnd_dai_stream_init(struct rsnd_dai_stream *io, diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 144308f..ac19ab1 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -36,7 +36,10 @@ static void rsnd_dmaen_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + bool elapsed = false; + unsigned long flags;
/* * Renesas sound Gen1 needs 1 DMAC, @@ -49,8 +52,14 @@ static void rsnd_dmaen_complete(void *data) * rsnd_dai_pointer_update() will be called twice, * ant it will breaks io->byte_pos */ + spin_lock_irqsave(&priv->lock, flags); + + elapsed = rsnd_dai_pointer_update(io, io->byte_per_period); + + spin_unlock_irqrestore(&priv->lock, flags);
- rsnd_dai_pointer_update(io, io->byte_per_period); + if (elapsed) + rsnd_dai_period_elapsed(io); }
static void rsnd_dmaen_stop(struct rsnd_dma *dma) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 03ff071..e37234e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -355,7 +355,8 @@ struct rsnd_dai {
struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
-void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); +bool rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt); +void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
/* diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 8569173..2548321 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -426,6 +426,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int is_dma = rsnd_ssi_is_dma_mode(mod); u32 status; + bool elapsed = false;
spin_lock(&priv->lock);
@@ -451,7 +452,7 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) else *buf = rsnd_mod_read(mod, SSIRDR);
- rsnd_dai_pointer_update(io, sizeof(*buf)); + elapsed = rsnd_dai_pointer_update(io, sizeof(*buf)); }
/* DMA only */ @@ -476,6 +477,9 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) rsnd_ssi_interrupt_out: spin_unlock(&priv->lock);
+ if (elapsed) + rsnd_dai_period_elapsed(io); + return IRQ_HANDLED; }
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current dai_link name is using "cpu_dai_name + codec_dai_name", but one of them is always "snd-soc-dummy-dai" when DPCM. This patch uses "fe.xxx" for cpu, "be.xxx" for codec.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 050b0db..9a1926f 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -55,11 +55,13 @@ struct rsrc_card_dai { #define RSRC_FB_NUM 2 /* FE/BE */ #define IDX_CPU 0 #define IDX_CODEC 1 +#define DAI_NAME_NUM 32 struct rsrc_card_priv { struct snd_soc_card snd_card; struct rsrc_card_dai_props { struct rsrc_card_dai cpu_dai; struct rsrc_card_dai codec_dai; + char dai_name[DAI_NAME_NUM]; } dai_props[RSRC_FB_NUM]; struct snd_soc_codec_conf codec_conf; struct snd_soc_dai_link dai_link[RSRC_FB_NUM]; @@ -309,7 +311,7 @@ static int rsrc_card_dai_link_of(struct device_node *node, struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); struct device_node *cpu = NULL; struct device_node *codec = NULL; - char *name; + char *name = dai_props->dai_name; char prop[128]; int ret, cpu_args;
@@ -348,18 +350,10 @@ static int rsrc_card_dai_link_of(struct device_node *node, /* Simple Card assumes platform == cpu */ dai_link->platform_of_node = dai_link->cpu_of_node;
- /* DAI link name is created from CPU/CODEC dai name */ - name = devm_kzalloc(dev, - strlen(dai_link->cpu_dai_name) + - strlen(dai_link->codec_dai_name) + 2, - GFP_KERNEL); - if (!name) { - ret = -ENOMEM; - goto dai_link_of_err; - } - - sprintf(name, "%s-%s", dai_link->cpu_dai_name, - dai_link->codec_dai_name); + snprintf(name, DAI_NAME_NUM, "%s.%s", + dai_link->dynamic ? "fe" : "be", + dai_link->dynamic ? dai_link->cpu_dai_name : + dai_link->codec_dai_name); dai_link->name = dai_link->stream_name = name; dai_link->ops = &rsrc_card_ops; dai_link->init = rsrc_card_dai_init;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 9a1926f..cdd005b 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -391,9 +391,9 @@ dai_link_of_err: }
static int rsrc_card_parse_of(struct device_node *node, - struct rsrc_card_priv *priv) + struct rsrc_card_priv *priv, + struct device *dev) { - struct device *dev = rsrc_priv_to_dev(priv); const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); int ret; int i; @@ -404,7 +404,13 @@ static int rsrc_card_parse_of(struct device_node *node, /* Parse the card name from DT */ snd_soc_of_parse_card_name(&priv->snd_card, "card-name");
- /* DAPM routes */ + /* Init snd_soc_card */ + priv->snd_card.owner = THIS_MODULE; + priv->snd_card.dev = dev; + priv->snd_card.dai_link = priv->dai_link; + priv->snd_card.num_links = RSRC_FB_NUM; + priv->snd_card.codec_conf = &priv->codec_conf; + priv->snd_card.num_configs = 1; priv->snd_card.of_dapm_routes = of_data->routes; priv->snd_card.num_of_dapm_routes = of_data->num_routes;
@@ -446,7 +452,6 @@ static int rsrc_card_unref(struct snd_soc_card *card) static int rsrc_card_probe(struct platform_device *pdev) { struct rsrc_card_priv *priv; - struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; int ret; @@ -456,16 +461,7 @@ static int rsrc_card_probe(struct platform_device *pdev) if (!priv) return -ENOMEM;
- /* Init snd_soc_card */ - priv->snd_card.owner = THIS_MODULE; - priv->snd_card.dev = dev; - dai_link = priv->dai_link; - priv->snd_card.dai_link = dai_link; - priv->snd_card.num_links = RSRC_FB_NUM; - priv->snd_card.codec_conf = &priv->codec_conf; - priv->snd_card.num_configs = 1; - - ret = rsrc_card_parse_of(np, priv); + ret = rsrc_card_parse_of(np, priv, dev); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current rsrc-card is assuming 1 FE (= CPU), 1 BE (= codec) on card. But, it will support multi FE/BE card. This is prepare for it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index cdd005b..ae99b36 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -52,7 +52,6 @@ struct rsrc_card_dai { struct clk *clk; };
-#define RSRC_FB_NUM 2 /* FE/BE */ #define IDX_CPU 0 #define IDX_CODEC 1 #define DAI_NAME_NUM 32 @@ -62,9 +61,10 @@ struct rsrc_card_priv { struct rsrc_card_dai cpu_dai; struct rsrc_card_dai codec_dai; char dai_name[DAI_NAME_NUM]; - } dai_props[RSRC_FB_NUM]; + } *dai_props; struct snd_soc_codec_conf codec_conf; - struct snd_soc_dai_link dai_link[RSRC_FB_NUM]; + struct snd_soc_dai_link *dai_link; + int dai_num; u32 convert_rate; };
@@ -395,12 +395,25 @@ static int rsrc_card_parse_of(struct device_node *node, struct device *dev) { const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); + struct rsrc_card_dai_props *props; + struct snd_soc_dai_link *links; + int ret; - int i; + int i, num;
if (!node) return -EINVAL;
+ num = of_get_child_count(node); + props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL); + links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL); + if (!props || !links) + return -ENOMEM; + + priv->dai_props = props; + priv->dai_link = links; + priv->dai_num = num; + /* Parse the card name from DT */ snd_soc_of_parse_card_name(&priv->snd_card, "card-name");
@@ -408,7 +421,7 @@ static int rsrc_card_parse_of(struct device_node *node, priv->snd_card.owner = THIS_MODULE; priv->snd_card.dev = dev; priv->snd_card.dai_link = priv->dai_link; - priv->snd_card.num_links = RSRC_FB_NUM; + priv->snd_card.num_links = num; priv->snd_card.codec_conf = &priv->codec_conf; priv->snd_card.num_configs = 1; priv->snd_card.of_dapm_routes = of_data->routes; @@ -422,7 +435,7 @@ static int rsrc_card_parse_of(struct device_node *node, priv->convert_rate);
/* FE/BE */ - for (i = 0; i < RSRC_FB_NUM; i++) { + for (i = 0; i < num; i++) { ret = rsrc_card_dai_link_of(node, priv, i); if (ret < 0) return ret;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index ae99b36..8c74b08 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -46,7 +46,6 @@ static const struct of_device_id rsrc_card_of_match[] = { MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
struct rsrc_card_dai { - const char *name; unsigned int fmt; unsigned int sysclk; struct clk *clk;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 8c74b08..8162b7d 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -68,8 +68,8 @@ struct rsrc_card_priv { };
#define rsrc_priv_to_dev(priv) ((priv)->snd_card.dev) -#define rsrc_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i) -#define rsrc_priv_to_props(priv, i) ((priv)->dai_props + i) +#define rsrc_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i)) +#define rsrc_priv_to_props(priv, i) ((priv)->dai_props + (i)) #define rsrc_dev_to_of_data(dev) (of_match_device(rsrc_card_of_match, (dev))->data)
static int rsrc_card_startup(struct snd_pcm_substream *substream) @@ -77,7 +77,7 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct rsrc_card_dai_props *dai_props = - &priv->dai_props[rtd - rtd->card->rtd]; + rsrc_priv_to_props(priv, rtd - rtd->card->rtd); int ret;
ret = clk_prepare_enable(dai_props->cpu_dai.clk); @@ -96,7 +96,7 @@ static void rsrc_card_shutdown(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct rsrc_card_dai_props *dai_props = - &priv->dai_props[rtd - rtd->card->rtd]; + rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
clk_disable_unprepare(dai_props->cpu_dai.clk);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
This is prepare for DPCM cleanup
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 70 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 35 deletions(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 8162b7d..d0d74b5 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -171,6 +171,41 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; }
+static int rsrc_card_parse_daifmt(struct device_node *node, + struct rsrc_card_priv *priv, + struct device_node *codec, + int idx) +{ + struct device_node *bitclkmaster = NULL; + struct device_node *framemaster = NULL; + struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); + struct rsrc_card_dai *cpu_dai = &dai_props->cpu_dai; + struct rsrc_card_dai *codec_dai = &dai_props->codec_dai; + unsigned int daifmt; + + daifmt = snd_soc_of_parse_daifmt(node, NULL, + &bitclkmaster, &framemaster); + daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; + + if (!bitclkmaster && !framemaster) + return -EINVAL; + + if (codec == bitclkmaster) + daifmt |= (codec == framemaster) ? + SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; + else + daifmt |= (codec == framemaster) ? + SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; + + cpu_dai->fmt = daifmt; + codec_dai->fmt = daifmt; + + of_node_put(bitclkmaster); + of_node_put(framemaster); + + return 0; +} + static int rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, struct device_node *np, @@ -266,41 +301,6 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, return 0; }
-static int rsrc_card_parse_daifmt(struct device_node *node, - struct rsrc_card_priv *priv, - struct device_node *codec, - int idx) -{ - struct device_node *bitclkmaster = NULL; - struct device_node *framemaster = NULL; - struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); - struct rsrc_card_dai *cpu_dai = &dai_props->cpu_dai; - struct rsrc_card_dai *codec_dai = &dai_props->codec_dai; - unsigned int daifmt; - - daifmt = snd_soc_of_parse_daifmt(node, NULL, - &bitclkmaster, &framemaster); - daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK; - - if (!bitclkmaster && !framemaster) - return -EINVAL; - - if (codec == bitclkmaster) - daifmt |= (codec == framemaster) ? - SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS; - else - daifmt |= (codec == framemaster) ? - SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; - - cpu_dai->fmt = daifmt; - codec_dai->fmt = daifmt; - - of_node_put(bitclkmaster); - of_node_put(framemaster); - - return 0; -} - static int rsrc_card_dai_link_of(struct device_node *node, struct rsrc_card_priv *priv, int idx)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index d0d74b5..52123d6 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -283,10 +283,8 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, */ if (of_property_read_bool(np, "clocks")) { clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - return ret; - } + if (IS_ERR(clk)) + return PTR_ERR(clk);
dai->sysclk = clk_get_rate(clk); dai->clk = clk;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
rsrc-card driver is based on simple-card driver which is caring about CPU / Codec connection. OTOH, rsrc-card is used for DPCM system. FE portion is constituted by CPU and dummy Codec, and BE is constituted by dummy CPU and Codec in DPCM system. Because of this, current rsrc-card is doing pointless method. It works well if FE/BE was 1:1, but not good for multi FE/BE. This patch cleanups rsrc-card driver for DPCM. and this is prepare for MIX support for Renesas sound driver.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/rsrc-card.c | 324 ++++++++++++++++++------------------------ 1 file changed, 135 insertions(+), 189 deletions(-)
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 52123d6..8caca2e 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -45,23 +45,20 @@ static const struct of_device_id rsrc_card_of_match[] = { }; MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
+#define DAI_NAME_NUM 32 struct rsrc_card_dai { unsigned int fmt; unsigned int sysclk; struct clk *clk; + char dai_name[DAI_NAME_NUM]; };
#define IDX_CPU 0 #define IDX_CODEC 1 -#define DAI_NAME_NUM 32 struct rsrc_card_priv { struct snd_soc_card snd_card; - struct rsrc_card_dai_props { - struct rsrc_card_dai cpu_dai; - struct rsrc_card_dai codec_dai; - char dai_name[DAI_NAME_NUM]; - } *dai_props; struct snd_soc_codec_conf codec_conf; + struct rsrc_card_dai *dai_props; struct snd_soc_dai_link *dai_link; int dai_num; u32 convert_rate; @@ -76,31 +73,22 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct rsrc_card_dai_props *dai_props = + struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, rtd - rtd->card->rtd); int ret;
- ret = clk_prepare_enable(dai_props->cpu_dai.clk); - if (ret) - return ret; - - ret = clk_prepare_enable(dai_props->codec_dai.clk); - if (ret) - clk_disable_unprepare(dai_props->cpu_dai.clk);
- return ret; + return clk_prepare_enable(dai_props->clk); }
static void rsrc_card_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct rsrc_card_dai_props *dai_props = + struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
- clk_disable_unprepare(dai_props->cpu_dai.clk); - - clk_disable_unprepare(dai_props->codec_dai.clk); + clk_disable_unprepare(dai_props->clk); }
static struct snd_soc_ops rsrc_card_ops = { @@ -108,21 +96,31 @@ static struct snd_soc_ops rsrc_card_ops = { .shutdown = rsrc_card_shutdown, };
-static int __rsrc_card_dai_init(struct snd_soc_dai *dai, - struct rsrc_card_dai *set) +static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) { + struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *dai; + struct snd_soc_dai_link *dai_link; + struct rsrc_card_dai *dai_props; + int num = rtd - rtd->card->rtd; int ret;
- if (set->fmt) { - ret = snd_soc_dai_set_fmt(dai, set->fmt); + dai_link = rsrc_priv_to_link(priv, num); + dai_props = rsrc_priv_to_props(priv, num); + dai = dai_link->dynamic ? + rtd->cpu_dai : + rtd->codec_dai; + + if (dai_props->fmt) { + ret = snd_soc_dai_set_fmt(dai, dai_props->fmt); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "set_fmt error\n"); goto err; } }
- if (set->sysclk) { - ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); + if (dai_props->sysclk) { + ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "set_sysclk error\n"); goto err; @@ -135,27 +133,6 @@ err: return ret; }
-static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd) -{ - struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *codec = rtd->codec_dai; - struct snd_soc_dai *cpu = rtd->cpu_dai; - struct rsrc_card_dai_props *dai_props; - int num, ret; - - num = rtd - rtd->card->rtd; - dai_props = &priv->dai_props[num]; - ret = __rsrc_card_dai_init(codec, &dai_props->codec_dai); - if (ret < 0) - return ret; - - ret = __rsrc_card_dai_init(cpu, &dai_props->cpu_dai); - if (ret < 0) - return ret; - - return 0; -} - static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -172,15 +149,14 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, }
static int rsrc_card_parse_daifmt(struct device_node *node, + struct device_node *np, struct rsrc_card_priv *priv, - struct device_node *codec, - int idx) + int idx, bool is_fe) { + struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); struct device_node *bitclkmaster = NULL; struct device_node *framemaster = NULL; - struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); - struct rsrc_card_dai *cpu_dai = &dai_props->cpu_dai; - struct rsrc_card_dai *codec_dai = &dai_props->codec_dai; + struct device_node *codec = is_fe ? NULL : np; unsigned int daifmt;
daifmt = snd_soc_of_parse_daifmt(node, NULL, @@ -197,8 +173,7 @@ static int rsrc_card_parse_daifmt(struct device_node *node, daifmt |= (codec == framemaster) ? SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
- cpu_dai->fmt = daifmt; - codec_dai->fmt = daifmt; + dai_props->fmt = daifmt;
of_node_put(bitclkmaster); of_node_put(framemaster); @@ -206,41 +181,15 @@ static int rsrc_card_parse_daifmt(struct device_node *node, return 0; }
-static int -rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, - struct device_node *np, - struct rsrc_card_dai *dai, - struct snd_soc_dai_link *dai_link, - int *args_count) +static int rsrc_card_parse_links(struct device_node *np, + struct rsrc_card_priv *priv, + int idx, bool is_fe) { - struct device *dev = rsrc_priv_to_dev(priv); - const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); + struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); + struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); struct of_phandle_args args; - struct device_node **p_node; - struct clk *clk; - const char **dai_name; - const char **name; - u32 val; int ret;
- if (args_count) { - p_node = &dai_link->cpu_of_node; - dai_name = &dai_link->cpu_dai_name; - name = &dai_link->cpu_name; - } else { - p_node = &dai_link->codec_of_node; - dai_name = &dai_link->codec_dai_name; - name = &dai_link->codec_name; - } - - if (!np) { - /* use snd-soc-dummy */ - *p_node = NULL; - *dai_name = "snd-soc-dummy-dai"; - *name = "snd-soc-dummy"; - return 0; - } - /* * Get node via "sound-dai = <&phandle port>" * it will be used as xxx_of_node on soc_bind_dai_link() @@ -250,31 +199,82 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, if (ret) return ret;
- *p_node = args.np; + if (is_fe) { + /* BE is dummy */ + dai_link->codec_of_node = NULL; + dai_link->codec_dai_name = "snd-soc-dummy-dai"; + dai_link->codec_name = "snd-soc-dummy"; + + /* FE settings */ + dai_link->dynamic = 1; + dai_link->dpcm_merged_format = 1; + dai_link->cpu_of_node = args.np; + snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name); + + /* set dai_name */ + snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s", + dai_link->cpu_dai_name); + + /* + * In soc_bind_dai_link() will check cpu name after + * of_node matching if dai_link has cpu_dai_name. + * but, it will never match if name was created by + * fmt_single_name() remove cpu_dai_name if cpu_args + * was 0. See: + * fmt_single_name() + * fmt_multiple_name() + */ + if (!args.args_count) + dai_link->cpu_dai_name = NULL; + } else { + struct device *dev = rsrc_priv_to_dev(priv); + const struct rsrc_card_of_data *of_data;
- /* Get dai->name */ - ret = snd_soc_of_get_dai_name(np, dai_name); - if (ret < 0) - return ret; + of_data = rsrc_dev_to_of_data(dev);
- /* - * FIXME - * - * rsrc assumes DPCM playback/capture - */ - dai_link->dpcm_playback = 1; - dai_link->dpcm_capture = 1; + /* FE is dummy */ + dai_link->cpu_of_node = NULL; + dai_link->cpu_dai_name = "snd-soc-dummy-dai"; + dai_link->cpu_name = "snd-soc-dummy";
- if (args_count) { - *args_count = args.args_count; - dai_link->dynamic = 1; - dai_link->dpcm_merged_format = 1; - } else { - dai_link->no_pcm = 1; - priv->codec_conf.of_node = (*p_node); - priv->codec_conf.name_prefix = of_data->prefix; + /* BE settings */ + dai_link->no_pcm = 1; + dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup; + dai_link->codec_of_node = args.np; + snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name); + + /* additional name prefix */ + priv->codec_conf.of_node = dai_link->codec_of_node; + priv->codec_conf.name_prefix = of_data->prefix; + + /* set dai_name */ + snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s", + dai_link->codec_dai_name); }
+ /* Simple Card assumes platform == cpu */ + dai_link->platform_of_node = dai_link->cpu_of_node; + dai_link->dpcm_playback = 1; + dai_link->dpcm_capture = 1; + dai_link->name = dai_props->dai_name; + dai_link->stream_name = dai_props->dai_name; + dai_link->ops = &rsrc_card_ops; + dai_link->init = rsrc_card_dai_init; + + return 0; +} + +static int rsrc_card_parse_clk(struct device_node *np, + struct rsrc_card_priv *priv, + int idx, bool is_fe) +{ + struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); + struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); + struct clk *clk; + struct device_node *of_np = is_fe ? dai_link->cpu_of_node : + dai_link->codec_of_node; + u32 val; + /* * Parse dai->sysclk come from "clocks = <&xxx>" * (if system has common clock) @@ -286,103 +286,48 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, if (IS_ERR(clk)) return PTR_ERR(clk);
- dai->sysclk = clk_get_rate(clk); - dai->clk = clk; + dai_props->sysclk = clk_get_rate(clk); + dai_props->clk = clk; } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { - dai->sysclk = val; + dai_props->sysclk = val; } else { - clk = of_clk_get(args.np, 0); + clk = of_clk_get(of_np, 0); if (!IS_ERR(clk)) - dai->sysclk = clk_get_rate(clk); + dai_props->sysclk = clk_get_rate(clk); }
return 0; }
static int rsrc_card_dai_link_of(struct device_node *node, + struct device_node *np, struct rsrc_card_priv *priv, int idx) { struct device *dev = rsrc_priv_to_dev(priv); - struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); - struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); - struct device_node *cpu = NULL; - struct device_node *codec = NULL; - char *name = dai_props->dai_name; - char prop[128]; - int ret, cpu_args; - - cpu = of_get_child_by_name(node, "cpu"); - codec = of_get_child_by_name(node, "codec"); - - if (!cpu || !codec) { - ret = -EINVAL; - dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop); - goto dai_link_of_err; - } + struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx); + bool is_fe = false; + int ret;
- ret = rsrc_card_parse_daifmt(node, priv, codec, idx); - if (ret < 0) - goto dai_link_of_err; + if (0 == strcmp(np->name, "cpu")) + is_fe = true;
- ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CPU) ? cpu : NULL, - &dai_props->cpu_dai, - dai_link, - &cpu_args); + ret = rsrc_card_parse_daifmt(node, np, priv, idx, is_fe); if (ret < 0) - goto dai_link_of_err; + return ret;
- ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CODEC) ? codec : NULL, - &dai_props->codec_dai, - dai_link, - NULL); + ret = rsrc_card_parse_links(np, priv, idx, is_fe); if (ret < 0) - goto dai_link_of_err; - - if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { - ret = -EINVAL; - goto dai_link_of_err; - } - - /* Simple Card assumes platform == cpu */ - dai_link->platform_of_node = dai_link->cpu_of_node; - - snprintf(name, DAI_NAME_NUM, "%s.%s", - dai_link->dynamic ? "fe" : "be", - dai_link->dynamic ? dai_link->cpu_dai_name : - dai_link->codec_dai_name); - dai_link->name = dai_link->stream_name = name; - dai_link->ops = &rsrc_card_ops; - dai_link->init = rsrc_card_dai_init; - - if (idx == IDX_CODEC) - dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup; - - dev_dbg(dev, "\tname : %s\n", dai_link->stream_name); - dev_dbg(dev, "\tcpu : %s / %04x / %d\n", - dai_link->cpu_dai_name, - dai_props->cpu_dai.fmt, - dai_props->cpu_dai.sysclk); - dev_dbg(dev, "\tcodec : %s / %04x / %d\n", - dai_link->codec_dai_name, - dai_props->codec_dai.fmt, - dai_props->codec_dai.sysclk); + return ret;
- /* - * In soc_bind_dai_link() will check cpu name after - * of_node matching if dai_link has cpu_dai_name. - * but, it will never match if name was created by - * fmt_single_name() remove cpu_dai_name if cpu_args - * was 0. See: - * fmt_single_name() - * fmt_multiple_name() - */ - if (!cpu_args) - dai_link->cpu_dai_name = NULL; + ret = rsrc_card_parse_clk(np, priv, idx, is_fe); + if (ret < 0) + return ret;
-dai_link_of_err: - of_node_put(cpu); - of_node_put(codec); + dev_dbg(dev, "\t%s / %04x / %d\n", + dai_props->dai_name, + dai_props->fmt, + dai_props->sysclk);
return ret; } @@ -392,9 +337,9 @@ static int rsrc_card_parse_of(struct device_node *node, struct device *dev) { const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); - struct rsrc_card_dai_props *props; + struct rsrc_card_dai *props; struct snd_soc_dai_link *links; - + struct device_node *np; int ret; int i, num;
@@ -411,9 +356,6 @@ static int rsrc_card_parse_of(struct device_node *node, priv->dai_link = links; priv->dai_num = num;
- /* Parse the card name from DT */ - snd_soc_of_parse_card_name(&priv->snd_card, "card-name"); - /* Init snd_soc_card */ priv->snd_card.owner = THIS_MODULE; priv->snd_card.dev = dev; @@ -424,6 +366,9 @@ static int rsrc_card_parse_of(struct device_node *node, priv->snd_card.of_dapm_routes = of_data->routes; priv->snd_card.num_of_dapm_routes = of_data->num_routes;
+ /* Parse the card name from DT */ + snd_soc_of_parse_card_name(&priv->snd_card, "card-name"); + /* sampling rate convert */ of_property_read_u32(node, "convert-rate", &priv->convert_rate);
@@ -431,11 +376,12 @@ static int rsrc_card_parse_of(struct device_node *node, priv->snd_card.name ? priv->snd_card.name : "", priv->convert_rate);
- /* FE/BE */ - for (i = 0; i < num; i++) { - ret = rsrc_card_dai_link_of(node, priv, i); + i = 0; + for_each_child_of_node(node, np) { + ret = rsrc_card_dai_link_of(node, np, priv, i); if (ret < 0) return ret; + i++; }
if (!priv->snd_card.name)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. Then, we don't need to re-call each mod function that had been called. This patch count each mod status.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 17 +++++++++++------ sound/soc/sh/rcar/rsnd.h | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 37 insertions(+), 21 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 027b043..50ec28c 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -211,15 +211,20 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) ({ \ struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ struct device *dev = rsnd_priv_to_dev(priv); \ - u32 mask = (1 << __rsnd_mod_shift_##func) & ~(1 << 31); \ - u32 call = __rsnd_mod_call_##func << __rsnd_mod_shift_##func; \ + u32 mask = 0xF << __rsnd_mod_shift_##func; \ + u8 val = (mod->status >> __rsnd_mod_shift_##func) & 0xF; \ + u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \ int ret = 0; \ - if ((mod->status & mask) == call) { \ - dev_dbg(dev, "%s[%d] %s\n", \ - rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ + int called = 0; \ + if (val == __rsnd_mod_call_##func) { \ + called = 1; \ ret = (mod)->ops->func(mod, param); \ - mod->status = (mod->status & ~mask) | (~call & mask); \ + mod->status = (mod->status & ~mask) + \ + (add << __rsnd_mod_shift_##func); \ } \ + dev_dbg(dev, "%s[%d] 0x%08x %s\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), mod->status, \ + called ? #func : ""); \ ret; \ })
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e37234e..8a114cb 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -259,25 +259,36 @@ struct rsnd_mod { /* * status * - * bit - * 0 0: probe 1: remove - * 1 0: init 1: quit - * 2 0: start 1: stop - * 3 0: pcm_new - * 4 0: fallback + * 0xH0000CBA * - * 31 bit is always called (see __rsnd_mod_call) - * 31 0: hw_params + * A 0: probe 1: remove + * B 0: init 1: quit + * C 0: start 1: stop + * + * H is always called (see __rsnd_mod_call) + * H 0: pcm_new + * H 0: fallback + * H 0: hw_params */ #define __rsnd_mod_shift_probe 0 #define __rsnd_mod_shift_remove 0 -#define __rsnd_mod_shift_init 1 -#define __rsnd_mod_shift_quit 1 -#define __rsnd_mod_shift_start 2 -#define __rsnd_mod_shift_stop 2 -#define __rsnd_mod_shift_pcm_new 3 -#define __rsnd_mod_shift_fallback 4 -#define __rsnd_mod_shift_hw_params 31 /* always called */ +#define __rsnd_mod_shift_init 4 +#define __rsnd_mod_shift_quit 4 +#define __rsnd_mod_shift_start 8 +#define __rsnd_mod_shift_stop 8 +#define __rsnd_mod_shift_pcm_new 28 /* always called */ +#define __rsnd_mod_shift_fallback 28 /* always called */ +#define __rsnd_mod_shift_hw_params 28 /* always called */ + +#define __rsnd_mod_add_probe 1 +#define __rsnd_mod_add_remove -1 +#define __rsnd_mod_add_init 1 +#define __rsnd_mod_add_quit -1 +#define __rsnd_mod_add_start 1 +#define __rsnd_mod_add_stop -1 +#define __rsnd_mod_add_pcm_new 0 +#define __rsnd_mod_add_fallback 0 +#define __rsnd_mod_add_hw_params 0
#define __rsnd_mod_call_probe 0 #define __rsnd_mod_call_remove 1
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This means we can't use rsnd_mod_to_io() in SSI/SRC/DMA interrupt handler. In such case, we need to check all io in interrupt handler, and then, "priv" is needed. This patch adds rsnd_priv pointer in rsnd_mod for prepare it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 4 +++- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/rsnd.h | 6 ++++-- sound/soc/sh/rcar/src.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 50ec28c..1e8d7e5 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -145,7 +145,8 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod) return mod->ops->dma_req(mod); }
-int rsnd_mod_init(struct rsnd_mod *mod, +int rsnd_mod_init(struct rsnd_priv *priv, + struct rsnd_mod *mod, struct rsnd_mod_ops *ops, struct clk *clk, enum rsnd_mod_type type, @@ -160,6 +161,7 @@ int rsnd_mod_init(struct rsnd_mod *mod, mod->ops = ops; mod->type = type; mod->clk = clk; + mod->priv = priv;
return ret; } diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index e5fcb06..2004bd0 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -366,7 +366,7 @@ int rsnd_dvc_probe(struct platform_device *pdev,
dvc->info = &info->dvc_info[i];
- ret = rsnd_mod_init(&dvc->mod, &rsnd_dvc_ops, + ret = rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, clk, RSND_MOD_DVC, i); if (ret) return ret; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8a114cb..4561b97 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -253,6 +253,7 @@ struct rsnd_mod { struct rsnd_mod_ops *ops; struct rsnd_dma dma; struct rsnd_dai_stream *io; + struct rsnd_priv *priv; struct clk *clk; u32 status; }; @@ -300,14 +301,15 @@ struct rsnd_mod { #define __rsnd_mod_call_fallback 0 #define __rsnd_mod_call_hw_params 0
-#define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod))) +#define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_dma(mod) (&(mod)->dma) #define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) #define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk)
-int rsnd_mod_init(struct rsnd_mod *mod, +int rsnd_mod_init(struct rsnd_priv *priv, + struct rsnd_mod *mod, struct rsnd_mod_ops *ops, struct clk *clk, enum rsnd_mod_type type, diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index fbe9166..316d139 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -1046,7 +1046,7 @@ int rsnd_src_probe(struct platform_device *pdev,
src->info = &info->src_info[i];
- ret = rsnd_mod_init(&src->mod, ops, clk, RSND_MOD_SRC, i); + ret = rsnd_mod_init(priv, &src->mod, ops, clk, RSND_MOD_SRC, i); if (ret) return ret; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2548321..16ced76 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -782,7 +782,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, else if (rsnd_ssi_pio_available(ssi)) ops = &rsnd_ssi_pio_ops;
- ret = rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i); + ret = rsnd_mod_init(priv, &ssi->mod, ops, clk, RSND_MOD_SSI, i); if (ret) return ret;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This means we can't call rsnd_mod_to_io() any more. This patch adds struct rsnd_dai_stream to each function as parameter.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 10 +++++----- sound/soc/sh/rcar/dvc.c | 8 ++++++-- sound/soc/sh/rcar/rsnd.h | 9 +++++++++ sound/soc/sh/rcar/src.c | 12 +++++++++++- sound/soc/sh/rcar/ssi.c | 24 +++++++++++++++++------- 5 files changed, 48 insertions(+), 15 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1e8d7e5..54297d7 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -209,7 +209,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) /* * rsnd_dai functions */ -#define __rsnd_mod_call(mod, func, param...) \ +#define __rsnd_mod_call(mod, io, func, param...) \ ({ \ struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ struct device *dev = rsnd_priv_to_dev(priv); \ @@ -220,7 +220,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) int called = 0; \ if (val == __rsnd_mod_call_##func) { \ called = 1; \ - ret = (mod)->ops->func(mod, param); \ + ret = (mod)->ops->func(mod, io, param); \ mod->status = (mod->status & ~mask) + \ (add << __rsnd_mod_shift_##func); \ } \ @@ -230,10 +230,10 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) ret; \ })
-#define rsnd_mod_call(mod, func, param...) \ +#define rsnd_mod_call(mod, io, func, param...) \ (!(mod) ? -ENODEV : \ !((mod)->ops->func) ? 0 : \ - __rsnd_mod_call(mod, func, param)) + __rsnd_mod_call(mod, io, func, param))
#define rsnd_dai_call(fn, io, param...) \ ({ \ @@ -243,7 +243,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) mod = (io)->mod[i]; \ if (!mod) \ continue; \ - ret = rsnd_mod_call(mod, fn, param); \ + ret = rsnd_mod_call(mod, io, fn, param); \ if (ret < 0) \ break; \ } \ diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 2004bd0..52e75eb 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -120,6 +120,7 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod) }
static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); @@ -134,9 +135,9 @@ static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod, }
static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod); struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); struct device *dev = rsnd_priv_to_dev(priv); int dvc_id = rsnd_mod_id(dvc_mod); @@ -181,6 +182,7 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, }
static int rsnd_dvc_quit(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { rsnd_mod_hw_stop(mod); @@ -189,6 +191,7 @@ static int rsnd_dvc_quit(struct rsnd_mod *mod, }
static int rsnd_dvc_start(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { rsnd_mod_write(mod, CMD_CTRL, 0x10); @@ -197,6 +200,7 @@ static int rsnd_dvc_start(struct rsnd_mod *mod, }
static int rsnd_dvc_stop(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { rsnd_mod_write(mod, CMD_CTRL, 0); @@ -205,9 +209,9 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod, }
static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); int is_play = rsnd_io_is_play(io); int ret; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4561b97..fd93a6a 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -226,23 +226,32 @@ struct rsnd_mod_ops { char *name; struct dma_chan* (*dma_req)(struct rsnd_mod *mod); int (*probe)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv); int (*remove)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv); int (*init)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv); int (*quit)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv); int (*start)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv); int (*stop)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv); int (*pcm_new)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd); int (*hw_params)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params); int (*fallback)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv); };
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 316d139..e28d9f6 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -316,6 +316,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) }
static int rsnd_src_hw_params(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *fe_params) { @@ -372,6 +373,7 @@ static int rsnd_src_init(struct rsnd_mod *mod, }
static int rsnd_src_quit(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_src *src = rsnd_mod_to_src(mod); @@ -532,6 +534,7 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod) }
static int rsnd_src_init_gen1(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { int ret; @@ -556,6 +559,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, }
static int rsnd_src_start_gen1(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { int id = rsnd_mod_id(mod); @@ -566,6 +570,7 @@ static int rsnd_src_start_gen1(struct rsnd_mod *mod, }
static int rsnd_src_stop_gen1(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { int id = rsnd_mod_id(mod); @@ -781,6 +786,7 @@ static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod) }
static int rsnd_src_probe_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_src *src = rsnd_mod_to_src(mod); @@ -810,6 +816,7 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod, }
static int rsnd_src_remove_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { rsnd_dma_quit(rsnd_mod_to_dma(mod)); @@ -818,6 +825,7 @@ static int rsnd_src_remove_gen2(struct rsnd_mod *mod, }
static int rsnd_src_init_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { int ret; @@ -838,6 +846,7 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, }
static int rsnd_src_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { rsnd_dma_start(rsnd_mod_to_dma(mod)); @@ -846,6 +855,7 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, }
static int rsnd_src_stop_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { int ret; @@ -878,10 +888,10 @@ static void rsnd_src_reconvert_update(struct rsnd_mod *mod) }
static int rsnd_src_pcm_new(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct rsnd_src *src = rsnd_mod_to_src(mod); int ret; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 16ced76..41ef475 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -281,10 +281,10 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) * SSI mod common functions */ static int rsnd_ssi_init(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr; @@ -332,6 +332,7 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, }
static int rsnd_ssi_quit(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); @@ -348,6 +349,7 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, }
static int rsnd_ssi_hw_params(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -371,7 +373,8 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod, /* It will be removed on rsnd_ssi_hw_stop */ ssi->chan = chan; if (ssi_parent) - return rsnd_ssi_hw_params(&ssi_parent->mod, substream, params); + return rsnd_ssi_hw_params(&ssi_parent->mod, io, + substream, params);
return 0; } @@ -388,10 +391,10 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) }
static int rsnd_ssi_start(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
rsnd_src_ssiu_start(mod, rsnd_ssi_use_busif(mod));
@@ -403,6 +406,7 @@ static int rsnd_ssi_start(struct rsnd_mod *mod, }
static int rsnd_ssi_stop(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); @@ -465,9 +469,9 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) dev_dbg(dev, "%s[%d] restart\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
- rsnd_ssi_stop(mod, priv); + rsnd_ssi_stop(mod, io, priv); if (ssi->err < 1024) - rsnd_ssi_start(mod, priv); + rsnd_ssi_start(mod, io, priv); else dev_warn(dev, "no more SSI restart\n"); } @@ -487,6 +491,7 @@ rsnd_ssi_interrupt_out: * SSI PIO */ static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -512,6 +517,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { };
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); @@ -534,6 +540,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, }
static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); @@ -549,6 +556,7 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, }
static int rsnd_ssi_fallback(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); @@ -569,23 +577,25 @@ static int rsnd_ssi_fallback(struct rsnd_mod *mod, }
static int rsnd_ssi_dma_start(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
rsnd_dma_start(dma);
- rsnd_ssi_start(mod, priv); + rsnd_ssi_start(mod, io, priv);
return 0; }
static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- rsnd_ssi_stop(mod, priv); + rsnd_ssi_stop(mod, io, priv);
rsnd_dma_stop(dma);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. Then, interrupt handler can't use rsnd_mod_to_io(). This patch adds SSI/SRC/DMA common interrupt handler frame
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 23 +++++++++++++++++++++++ sound/soc/sh/rcar/rsnd.h | 3 +++ 2 files changed, 26 insertions(+)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 54297d7..424d1a3 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -172,6 +172,29 @@ void rsnd_mod_quit(struct rsnd_mod *mod) clk_unprepare(mod->clk); }
+void rsnd_mod_interrupt(struct rsnd_mod *mod, + void (*callback)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io)) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io; + struct rsnd_dai *rdai; + int i, j; + + for_each_rsnd_dai(rdai, priv, j) { + + for (i = 0; i < RSND_MOD_MAX; i++) { + io = &rdai->playback; + if (mod == io->mod[i]) + callback(mod, io); + + io = &rdai->capture; + if (mod == io->mod[i]) + callback(mod, io); + } + } +} + int rsnd_mod_is_working(struct rsnd_mod *mod) { struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index fd93a6a..e6aad5e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -327,6 +327,9 @@ void rsnd_mod_quit(struct rsnd_mod *mod); char *rsnd_mod_name(struct rsnd_mod *mod); int rsnd_mod_is_working(struct rsnd_mod *mod); struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod); +void rsnd_mod_interrupt(struct rsnd_mod *mod, + void (*callback)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io));
/* * R-Car sound DAI
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This patch removes rsnd_mod_to_io() from rsnd_get_adinr() and its related function
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 3 +-- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/rsnd.h | 6 ++++-- sound/soc/sh/rcar/src.c | 28 +++++++++++++++------------- sound/soc/sh/rcar/ssi.c | 4 ++-- 5 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 424d1a3..e1d1b22f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -206,10 +206,9 @@ int rsnd_mod_is_working(struct rsnd_mod *mod) /* * settting function */ -u32 rsnd_get_adinr(struct rsnd_mod *mod) +u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); u32 adinr = runtime->channels; diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 52e75eb..691bc63 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -169,7 +169,7 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
rsnd_mod_write(dvc_mod, DVC_DVUIR, 1);
- rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); + rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod, io));
/* ch0/ch1 Volume */ rsnd_dvc_volume_update(dvc_mod); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e6aad5e..b40435d 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -165,7 +165,7 @@ void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, u32 data); void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, u32 mask, u32 data); -u32 rsnd_get_adinr(struct rsnd_mod *mod); +u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
/* * R-Car DMA @@ -537,8 +537,10 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, int use_busif); -int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod); +int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io); int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod); int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod);
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index e28d9f6..5693bb5 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -129,9 +129,9 @@ static struct dma_chan *rsnd_src_dma_req(struct rsnd_mod *mod) }
int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io, int use_busif) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); int ssi_id = rsnd_mod_id(ssi_mod); @@ -174,7 +174,7 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, u32 mask = ~0;
rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, - rsnd_get_adinr(ssi_mod)); + rsnd_get_adinr(ssi_mod, io)); rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1);
@@ -196,7 +196,8 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, return 0; }
-int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod) +int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod, + struct rsnd_dai_stream *io) { /* * DMA settings for SSIU @@ -283,9 +284,9 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, return rate; }
-static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) +static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 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); @@ -299,7 +300,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod) rsnd_mod_write(mod, SRC_SWRSR, 1);
/* Set channel number and output bit length */ - rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod)); + rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod, io));
/* Enable the initial value of IFS */ if (fsrate) { @@ -508,12 +509,13 @@ static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod) return 0; }
-static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod) +static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { struct rsnd_src *src = rsnd_mod_to_src(mod); int ret;
- ret = rsnd_src_set_convert_rate(mod); + ret = rsnd_src_set_convert_rate(mod, io); if (ret < 0) return ret;
@@ -547,7 +549,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_src_set_convert_rate_gen1(mod); + ret = rsnd_src_set_convert_rate_gen1(mod, io); if (ret < 0) return ret;
@@ -706,11 +708,11 @@ rsnd_src_interrupt_gen2_out: return IRQ_HANDLED; }
-static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod) +static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 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); @@ -731,7 +733,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod) return -EINVAL; }
- ret = rsnd_src_set_convert_rate(mod); + ret = rsnd_src_set_convert_rate(mod, io); if (ret < 0) return ret;
@@ -834,7 +836,7 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_src_set_convert_rate_gen2(mod); + ret = rsnd_src_set_convert_rate_gen2(mod, io); if (ret < 0) return ret;
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 41ef475..564e829 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -396,7 +396,7 @@ static int rsnd_ssi_start(struct rsnd_mod *mod, { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- rsnd_src_ssiu_start(mod, rsnd_ssi_use_busif(mod)); + rsnd_src_ssiu_start(mod, io, rsnd_ssi_use_busif(mod));
rsnd_ssi_hw_start(ssi, io);
@@ -417,7 +417,7 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
rsnd_ssi_hw_stop(ssi);
- rsnd_src_ssiu_stop(mod); + rsnd_src_ssiu_stop(mod, io);
return 0; }
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This patch removes rsnd_mod_to_io() from rsnd_dma_xxx() and related function
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 5 ++- sound/soc/sh/rcar/dma.c | 102 ++++++++++++++++++++++++++--------------------- sound/soc/sh/rcar/dvc.c | 3 +- sound/soc/sh/rcar/rsnd.h | 22 +++++----- sound/soc/sh/rcar/src.c | 12 +++--- sound/soc/sh/rcar/ssi.c | 12 +++--- 6 files changed, 85 insertions(+), 71 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index e1d1b22f..daa01e2 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -137,12 +137,13 @@ char *rsnd_mod_name(struct rsnd_mod *mod) return mod->ops->name; }
-struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod) +struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { if (!mod || !mod->ops || !mod->ops->dma_req) return NULL;
- return mod->ops->dma_req(mod); + return mod->ops->dma_req(io, mod); }
int rsnd_mod_init(struct rsnd_priv *priv, diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index ac19ab1..a4ac510 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -32,12 +32,10 @@ struct rsnd_dma_ctrl { /* * Audio DMAC */ -static void rsnd_dmaen_complete(void *data) +static void __rsnd_dmaen_complete(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { - struct rsnd_dma *dma = (struct rsnd_dma *)data; - struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); bool elapsed = false; unsigned long flags;
@@ -54,7 +52,8 @@ static void rsnd_dmaen_complete(void *data) */ spin_lock_irqsave(&priv->lock, flags);
- elapsed = rsnd_dai_pointer_update(io, io->byte_per_period); + if (rsnd_mod_is_working(mod)) + elapsed = rsnd_dai_pointer_update(io, io->byte_per_period);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -62,19 +61,25 @@ static void rsnd_dmaen_complete(void *data) rsnd_dai_period_elapsed(io); }
-static void rsnd_dmaen_stop(struct rsnd_dma *dma) +static void rsnd_dmaen_complete(void *data) +{ + struct rsnd_mod *mod = data; + + rsnd_mod_interrupt(mod, __rsnd_dmaen_complete); +} + +static void rsnd_dmaen_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
dmaengine_terminate_all(dmaen->chan); }
-static void rsnd_dmaen_start(struct rsnd_dma *dma) +static void rsnd_dmaen_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_substream *substream = io->substream; struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; @@ -93,7 +98,7 @@ static void rsnd_dmaen_start(struct rsnd_dma *dma) }
desc->callback = rsnd_dmaen_complete; - desc->callback_param = dma; + desc->callback_param = mod;
if (dmaengine_submit(desc) < 0) { dev_err(dev, "dmaengine_submit() fail\n"); @@ -124,7 +129,8 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, return chan; }
-static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_mod *mod_from, +static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io, + struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { if ((!mod_from && !mod_to) || @@ -132,19 +138,19 @@ static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_mod *mod_from, return NULL;
if (mod_from) - return rsnd_mod_dma_req(mod_from); + return rsnd_mod_dma_req(io, mod_from); else - return rsnd_mod_dma_req(mod_to); + return rsnd_mod_dma_req(io, mod_to); }
-static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, +static int rsnd_dmaen_init(struct rsnd_dai_stream *io, + struct rsnd_dma *dma, int id, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); + struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg = {}; - struct rsnd_mod *mod = rsnd_dma_to_mod(dma); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int is_play = rsnd_io_is_play(io); int ret;
@@ -154,7 +160,7 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, }
if (dev->of_node) { - dmaen->chan = rsnd_dmaen_request_channel(mod_from, mod_to); + dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to); } else { dma_cap_mask_t mask;
@@ -186,7 +192,7 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, return 0;
rsnd_dma_init_err: - rsnd_dma_quit(dma); + rsnd_dma_quit(io, dma); rsnd_dma_channel_err:
/* @@ -198,7 +204,7 @@ rsnd_dma_channel_err: return -EAGAIN; }
-static void rsnd_dmaen_quit(struct rsnd_dma *dma) +static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
@@ -247,9 +253,9 @@ static const u8 gen2_id_table_cmd[] = { 0x38, /* SCU_CMD1 */ };
-static u32 rsnd_dmapp_get_id(struct rsnd_mod *mod) +static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); @@ -277,11 +283,12 @@ static u32 rsnd_dmapp_get_id(struct rsnd_mod *mod) return entry[id]; }
-static u32 rsnd_dmapp_get_chcr(struct rsnd_mod *mod_from, +static u32 rsnd_dmapp_get_chcr(struct rsnd_dai_stream *io, + struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { - return (rsnd_dmapp_get_id(mod_from) << 24) + - (rsnd_dmapp_get_id(mod_to) << 16); + return (rsnd_dmapp_get_id(io, mod_from) << 24) + + (rsnd_dmapp_get_id(io, mod_to) << 16); }
#define rsnd_dmapp_addr(dmac, dma, reg) \ @@ -308,7 +315,7 @@ static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg) return ioread32(rsnd_dmapp_addr(dmac, dma, reg)); }
-static void rsnd_dmapp_stop(struct rsnd_dma *dma) +static void rsnd_dmapp_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { int i;
@@ -321,7 +328,7 @@ static void rsnd_dmapp_stop(struct rsnd_dma *dma) } }
-static void rsnd_dmapp_start(struct rsnd_dma *dma) +static void rsnd_dmapp_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
@@ -330,19 +337,21 @@ static void rsnd_dmapp_start(struct rsnd_dma *dma) rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR); }
-static int rsnd_dmapp_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, +static int rsnd_dmapp_init(struct rsnd_dai_stream *io, + struct rsnd_dma *dma, int id, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); + struct rsnd_priv *priv = rsnd_io_to_priv(io); struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); struct device *dev = rsnd_priv_to_dev(priv);
dmapp->dmapp_id = dmac->dmapp_num; - dmapp->chcr = rsnd_dmapp_get_chcr(mod_from, mod_to) | PDMACHCR_DE; + dmapp->chcr = rsnd_dmapp_get_chcr(io, mod_from, mod_to) | PDMACHCR_DE;
dmac->dmapp_num++;
- rsnd_dmapp_stop(dma); + rsnd_dmapp_stop(io, dma);
dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n", dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr); @@ -395,12 +404,12 @@ static struct rsnd_dma_ops rsnd_dmapp_ops = { #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
static dma_addr_t -rsnd_gen2_dma_addr(struct rsnd_priv *priv, +rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod, int is_play, int is_from) { + struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); @@ -455,10 +464,12 @@ rsnd_gen2_dma_addr(struct rsnd_priv *priv, dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; }
-static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv, +static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod, int is_play, int is_from) { + struct rsnd_priv *priv = rsnd_io_to_priv(io); + /* * gen1 uses default DMA addr */ @@ -468,17 +479,17 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv, if (!mod) return 0;
- return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); + return rsnd_gen2_dma_addr(io, mod, is_play, is_from); }
#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ static void rsnd_dma_of_path(struct rsnd_dma *dma, + struct rsnd_dai_stream *io, int is_play, struct rsnd_mod **mod_from, struct rsnd_mod **mod_to) { struct rsnd_mod *this = rsnd_dma_to_mod(dma); - struct rsnd_dai_stream *io = rsnd_mod_to_io(this); struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); @@ -533,17 +544,17 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma, } }
-void rsnd_dma_stop(struct rsnd_dma *dma) +void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { - dma->ops->stop(dma); + dma->ops->stop(io, dma); }
-void rsnd_dma_start(struct rsnd_dma *dma) +void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { - dma->ops->start(dma); + dma->ops->start(io, dma); }
-void rsnd_dma_quit(struct rsnd_dma *dma) +void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) { struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); @@ -552,15 +563,14 @@ void rsnd_dma_quit(struct rsnd_dma *dma) if (!dmac) return;
- dma->ops->quit(dma); + dma->ops->quit(io, dma); }
-int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) +int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) { - struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_mod *mod_from; struct rsnd_mod *mod_to; - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct rsnd_priv *priv = rsnd_io_to_priv(io); struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); int is_play = rsnd_io_is_play(io);
@@ -573,10 +583,10 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) if (!dmac) return -EAGAIN;
- rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); + rsnd_dma_of_path(dma, io, is_play, &mod_from, &mod_to);
- dma->src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1); - dma->dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0); + dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); + dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0);
/* for Gen2 */ if (mod_from && mod_to) @@ -588,7 +598,7 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) if (rsnd_is_gen1(priv)) dma->ops = &rsnd_dmaen_ops;
- return dma->ops->init(priv, dma, id, mod_from, mod_to); + return dma->ops->init(io, dma, id, mod_from, mod_to); }
int rsnd_dma_probe(struct platform_device *pdev, diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 691bc63..3aac7905 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -265,7 +265,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, return 0; }
-static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_mod *mod) +static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b40435d..19d0d8b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -172,11 +172,11 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod, struct rsnd_dai_stream *io); */ struct rsnd_dma; struct rsnd_dma_ops { - void (*start)(struct rsnd_dma *dma); - void (*stop)(struct rsnd_dma *dma); - int (*init)(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, + void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); + void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); + int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to); - void (*quit)(struct rsnd_dma *dma); + void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma); };
struct rsnd_dmaen { @@ -200,10 +200,10 @@ struct rsnd_dma { #define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) #define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
-void rsnd_dma_start(struct rsnd_dma *dma); -void rsnd_dma_stop(struct rsnd_dma *dma); -int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id); -void rsnd_dma_quit(struct rsnd_dma *dma); +void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma); +void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma); +int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id); +void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma); int rsnd_dma_probe(struct platform_device *pdev, const struct rsnd_of_data *of_data, struct rsnd_priv *priv); @@ -224,7 +224,8 @@ enum rsnd_mod_type {
struct rsnd_mod_ops { char *name; - struct dma_chan* (*dma_req)(struct rsnd_mod *mod); + struct dma_chan* (*dma_req)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod); int (*probe)(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv); @@ -326,7 +327,8 @@ int rsnd_mod_init(struct rsnd_priv *priv, void rsnd_mod_quit(struct rsnd_mod *mod); char *rsnd_mod_name(struct rsnd_mod *mod); int rsnd_mod_is_working(struct rsnd_mod *mod); -struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod); +struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, + struct rsnd_mod *mod); void rsnd_mod_interrupt(struct rsnd_mod *mod, void (*callback)(struct rsnd_mod *mod, struct rsnd_dai_stream *io)); diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 5693bb5..6221619 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -117,10 +117,10 @@ struct rsnd_src { /* * Gen1/Gen2 common functions */ -static struct dma_chan *rsnd_src_dma_req(struct rsnd_mod *mod) +static struct dma_chan *rsnd_src_dma_req(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int is_play = rsnd_io_is_play(io);
return rsnd_dma_request_channel(rsnd_src_of_node(priv), @@ -810,7 +810,7 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod, return ret; }
- ret = rsnd_dma_init(priv, + ret = rsnd_dma_init(io, rsnd_mod_to_dma(mod), src->info->dma_id);
@@ -821,7 +821,7 @@ static int rsnd_src_remove_gen2(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { - rsnd_dma_quit(rsnd_mod_to_dma(mod)); + rsnd_dma_quit(io, rsnd_mod_to_dma(mod));
return 0; } @@ -851,7 +851,7 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { - rsnd_dma_start(rsnd_mod_to_dma(mod)); + rsnd_dma_start(io, rsnd_mod_to_dma(mod));
return _rsnd_src_start_gen2(mod); } @@ -864,7 +864,7 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
ret = _rsnd_src_stop_gen2(mod);
- rsnd_dma_stop(rsnd_mod_to_dma(mod)); + rsnd_dma_stop(io, rsnd_mod_to_dma(mod));
return ret; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 564e829..0a32544 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -533,7 +533,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, return ret;
ret = rsnd_dma_init( - priv, rsnd_mod_to_dma(mod), + io, rsnd_mod_to_dma(mod), dma_id);
return ret; @@ -547,7 +547,7 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, struct device *dev = rsnd_priv_to_dev(priv); int irq = ssi->info->irq;
- rsnd_dma_quit(rsnd_mod_to_dma(mod)); + rsnd_dma_quit(io, rsnd_mod_to_dma(mod));
/* PIO will request IRQ again */ devm_free_irq(dev, irq, ssi); @@ -582,7 +582,7 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, { struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- rsnd_dma_start(dma); + rsnd_dma_start(io, dma);
rsnd_ssi_start(mod, io, priv);
@@ -597,15 +597,15 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
rsnd_ssi_stop(mod, io, priv);
- rsnd_dma_stop(dma); + rsnd_dma_stop(io, dma);
return 0; }
-static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_mod *mod) +static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int is_play = rsnd_io_is_play(io); char *name;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This patch removes rsnd_mod_to_io() from rsnd_ssi_xxx() and related function.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/dma.c | 2 +- sound/soc/sh/rcar/rsnd.h | 2 +- sound/soc/sh/rcar/ssi.c | 32 ++++++++++++++++++-------------- 3 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index a4ac510..48b87bb 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -456,7 +456,7 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, dev_err(dev, "DVC is selected without SRC\n");
/* use SSIU or SSI ? */ - if (is_ssi && rsnd_ssi_use_busif(mod)) + if (is_ssi && rsnd_ssi_use_busif(io, mod)) is_ssi++;
return (is_from) ? diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 19d0d8b..ac03d20 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -559,7 +559,7 @@ void rsnd_ssi_remove(struct platform_device *pdev, struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); -int rsnd_ssi_use_busif(struct rsnd_mod *mod); +int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
/* * R-Car DVC diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0a32544..fa1f2e5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -87,10 +87,9 @@ struct rsnd_ssi { #define rsnd_ssi_of_node(priv) \ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi")
-int rsnd_ssi_use_busif(struct rsnd_mod *mod) +int rsnd_ssi_use_busif(struct rsnd_dai_stream *io, struct rsnd_mod *mod) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int use_busif = 0;
if (!rsnd_ssi_is_dma_mode(mod)) @@ -226,10 +225,9 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); }
-static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) +static void rsnd_ssi_hw_stop(struct rsnd_dai_stream *io, struct rsnd_ssi *ssi) { struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(&ssi->mod); struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct device *dev = rsnd_priv_to_dev(priv); u32 cr; @@ -263,7 +261,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
if (ssi_parent) - rsnd_ssi_hw_stop(ssi_parent); + rsnd_ssi_hw_stop(io, ssi_parent); else rsnd_ssi_master_clk_stop(ssi); } @@ -396,7 +394,7 @@ static int rsnd_ssi_start(struct rsnd_mod *mod, { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- rsnd_src_ssiu_start(mod, io, rsnd_ssi_use_busif(mod)); + rsnd_src_ssiu_start(mod, io, rsnd_ssi_use_busif(io, mod));
rsnd_ssi_hw_start(ssi, io);
@@ -415,19 +413,18 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR));
- rsnd_ssi_hw_stop(ssi); + rsnd_ssi_hw_stop(io, ssi);
rsnd_src_ssiu_stop(mod, io);
return 0; }
-static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) +static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { - struct rsnd_ssi *ssi = data; - struct rsnd_mod *mod = &ssi->mod; + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int is_dma = rsnd_ssi_is_dma_mode(mod); u32 status; bool elapsed = false; @@ -483,6 +480,13 @@ rsnd_ssi_interrupt_out:
if (elapsed) rsnd_dai_period_elapsed(io); +} + +static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) +{ + struct rsnd_mod *mod = data; + + rsnd_mod_interrupt(mod, __rsnd_ssi_interrupt);
return IRQ_HANDLED; } @@ -501,7 +505,7 @@ static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, ret = devm_request_irq(dev, ssi->info->irq, rsnd_ssi_interrupt, IRQF_SHARED, - dev_name(dev), ssi); + dev_name(dev), mod);
return ret; } @@ -528,7 +532,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, ret = devm_request_irq(dev, ssi->info->irq, rsnd_ssi_interrupt, IRQF_SHARED, - dev_name(dev), ssi); + dev_name(dev), mod); if (ret) return ret;
@@ -609,7 +613,7 @@ static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io, int is_play = rsnd_io_is_play(io); char *name;
- if (rsnd_ssi_use_busif(mod)) + if (rsnd_ssi_use_busif(io, mod)) name = is_play ? "rxu" : "txu"; else name = is_play ? "rx" : "tx";
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This patch removes rsnd_mod_to_io() from rsnd_src_xxx() and related function.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/src.c | 57 +++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 25 deletions(-)
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 6221619..bc122ed 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -236,10 +236,9 @@ int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod) return 0; }
-static u32 rsnd_src_convert_rate(struct rsnd_src *src) +static u32 rsnd_src_convert_rate(struct rsnd_dai_stream *io, + struct rsnd_src *src) { - struct rsnd_mod *mod = &src->mod; - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 convert_rate;
@@ -275,7 +274,7 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, * return convert rate if SRC is used, * otherwise, return runtime->rate as usual */ - rate = rsnd_src_convert_rate(src); + rate = rsnd_src_convert_rate(io, src); }
if (!rate) @@ -289,7 +288,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, { 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 convert_rate = rsnd_src_convert_rate(io, src); u32 fsrate = 0;
if (convert_rate) @@ -414,9 +413,9 @@ static int rsnd_src_stop(struct rsnd_mod *mod) /* * Gen1 functions */ -static int rsnd_src_set_route_gen1(struct rsnd_mod *mod) +static int rsnd_src_set_route_gen1(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct src_route_config { u32 mask; int shift; @@ -451,13 +450,13 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod) return 0; }
-static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod) +static int rsnd_src_set_convert_timing_gen1(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 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_src_convert_rate(src); + u32 convert_rate = rsnd_src_convert_rate(io, src); u32 mask; u32 val; int shift; @@ -527,7 +526,7 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98);
/* Gen1/Gen2 are not compatible */ - if (rsnd_src_convert_rate(src)) + if (rsnd_src_convert_rate(io, src)) rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1);
/* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */ @@ -545,7 +544,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_src_set_route_gen1(mod); + ret = rsnd_src_set_route_gen1(io, mod); if (ret < 0) return ret;
@@ -553,7 +552,7 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_src_set_convert_timing_gen1(mod); + ret = rsnd_src_set_convert_timing_gen1(io, mod); if (ret < 0) return ret;
@@ -650,9 +649,9 @@ static bool rsnd_src_error_record_gen2(struct rsnd_mod *mod) return ret; }
-static int _rsnd_src_start_gen2(struct rsnd_mod *mod) +static int _rsnd_src_start_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11;
rsnd_mod_write(mod, SRC_CTRL, val); @@ -677,9 +676,9 @@ static int _rsnd_src_stop_gen2(struct rsnd_mod *mod) return rsnd_src_stop(mod); }
-static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) +static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod, + struct rsnd_dai_stream *io) { - struct rsnd_mod *mod = data; struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
spin_lock(&priv->lock); @@ -698,12 +697,20 @@ static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data)
_rsnd_src_stop_gen2(mod); if (src->err < 1024) - _rsnd_src_start_gen2(mod); + _rsnd_src_start_gen2(mod, io); else dev_warn(dev, "no more SRC restart\n"); } + rsnd_src_interrupt_gen2_out: spin_unlock(&priv->lock); +} + +static irqreturn_t rsnd_src_interrupt_gen2(int irq, void *data) +{ + struct rsnd_mod *mod = data; + + rsnd_mod_interrupt(mod, __rsnd_src_interrupt_gen2);
return IRQ_HANDLED; } @@ -715,7 +722,7 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, struct device *dev = rsnd_priv_to_dev(priv); 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 convert_rate = rsnd_src_convert_rate(io, src); u32 cr, route; uint ratio; int ret; @@ -769,12 +776,12 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, return 0; }
-static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod) +static int rsnd_src_set_convert_timing_gen2(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 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 convert_rate = rsnd_src_convert_rate(io, src); int ret;
if (convert_rate) @@ -840,7 +847,7 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_src_set_convert_timing_gen2(mod); + ret = rsnd_src_set_convert_timing_gen2(io, mod); if (ret < 0) return ret;
@@ -853,7 +860,7 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, { rsnd_dma_start(io, rsnd_mod_to_dma(mod));
- return _rsnd_src_start_gen2(mod); + return _rsnd_src_start_gen2(mod, io); }
static int rsnd_src_stop_gen2(struct rsnd_mod *mod, @@ -874,7 +881,7 @@ static void rsnd_src_reconvert_update(struct rsnd_mod *mod) struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 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 convert_rate = rsnd_src_convert_rate(io, src); u32 fsrate;
if (!runtime)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This patch removes rsnd_mod_to_io() from snd_kcontrol and related function.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 25 +++++++++++++++++-------- sound/soc/sh/rcar/dvc.c | 15 ++++++++------- sound/soc/sh/rcar/rsnd.h | 15 +++++++++++---- sound/soc/sh/rcar/src.c | 8 ++++---- 4 files changed, 40 insertions(+), 23 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index daa01e2..266b24a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -880,16 +880,18 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, }
if (change) - cfg->update(mod); + cfg->update(cfg->io, mod);
return change; }
static int __rsnd_kctrl_new(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd, const unsigned char *name, struct rsnd_kctrl_cfg *cfg, - void (*update)(struct rsnd_mod *mod)) + void (*update)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod)) { struct snd_soc_card *soc_card = rtd->card; struct snd_card *card = rtd->card->snd_card; @@ -918,6 +920,7 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod, cfg->update = update; cfg->card = card; cfg->kctrl = kctrl; + cfg->io = io;
return 0; } @@ -928,36 +931,42 @@ void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg) }
int rsnd_kctrl_new_m(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd, const unsigned char *name, - void (*update)(struct rsnd_mod *mod), + void (*update)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod), struct rsnd_kctrl_cfg_m *_cfg, u32 max) { _cfg->cfg.max = max; _cfg->cfg.size = RSND_DVC_CHANNELS; _cfg->cfg.val = _cfg->val; - return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); + return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update); }
int rsnd_kctrl_new_s(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd, const unsigned char *name, - void (*update)(struct rsnd_mod *mod), + void (*update)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod), struct rsnd_kctrl_cfg_s *_cfg, u32 max) { _cfg->cfg.max = max; _cfg->cfg.size = 1; _cfg->cfg.val = &_cfg->val; - return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); + return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update); }
int rsnd_kctrl_new_e(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd, const unsigned char *name, struct rsnd_kctrl_cfg_s *_cfg, - void (*update)(struct rsnd_mod *mod), + void (*update)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod), const char * const *texts, u32 max) { @@ -965,7 +974,7 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod, _cfg->cfg.size = 1; _cfg->cfg.val = &_cfg->val; _cfg->cfg.texts = texts; - return __rsnd_kctrl_new(mod, rtd, name, &_cfg->cfg, update); + return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update); }
/* diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 3aac7905..36fc020 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -63,7 +63,8 @@ static const char * const dvc_ramp_rate[] = { "0.125 dB/8192 steps", /* 10111 */ };
-static void rsnd_dvc_volume_update(struct rsnd_mod *mod) +static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); u32 val[RSND_DVC_CHANNELS]; @@ -172,7 +173,7 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod, io));
/* ch0/ch1 Volume */ - rsnd_dvc_volume_update(dvc_mod); + rsnd_dvc_volume_update(io, dvc_mod);
rsnd_mod_write(dvc_mod, DVC_DVUIR, 0);
@@ -217,7 +218,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, int ret;
/* Volume */ - ret = rsnd_kctrl_new_m(mod, rtd, + ret = rsnd_kctrl_new_m(mod, io, rtd, is_play ? "DVC Out Playback Volume" : "DVC In Capture Volume", rsnd_dvc_volume_update, @@ -226,7 +227,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, return ret;
/* Mute */ - ret = rsnd_kctrl_new_m(mod, rtd, + ret = rsnd_kctrl_new_m(mod, io, rtd, is_play ? "DVC Out Mute Switch" : "DVC In Mute Switch", rsnd_dvc_volume_update, @@ -235,7 +236,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, return ret;
/* Ramp */ - ret = rsnd_kctrl_new_s(mod, rtd, + ret = rsnd_kctrl_new_s(mod, io, rtd, is_play ? "DVC Out Ramp Switch" : "DVC In Ramp Switch", rsnd_dvc_volume_update, @@ -243,7 +244,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_kctrl_new_e(mod, rtd, + ret = rsnd_kctrl_new_e(mod, io, rtd, is_play ? "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate", &dvc->rup, @@ -252,7 +253,7 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_kctrl_new_e(mod, rtd, + ret = rsnd_kctrl_new_e(mod, io, rtd, is_play ? "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate", &dvc->rdown, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index ac03d20..fdb443b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -487,7 +487,8 @@ struct rsnd_kctrl_cfg { unsigned int size; u32 *val; const char * const *texts; - void (*update)(struct rsnd_mod *mod); + void (*update)(struct rsnd_dai_stream *io, struct rsnd_mod *mod); + struct rsnd_dai_stream *io; struct snd_card *card; struct snd_kcontrol *kctrl; }; @@ -507,22 +508,28 @@ void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg); #define rsnd_kctrl_remove(_cfg) _rsnd_kctrl_remove(&((_cfg).cfg))
int rsnd_kctrl_new_m(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd, const unsigned char *name, - void (*update)(struct rsnd_mod *mod), + void (*update)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod), struct rsnd_kctrl_cfg_m *_cfg, u32 max); int rsnd_kctrl_new_s(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd, const unsigned char *name, - void (*update)(struct rsnd_mod *mod), + void (*update)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod), struct rsnd_kctrl_cfg_s *_cfg, u32 max); int rsnd_kctrl_new_e(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd, const unsigned char *name, struct rsnd_kctrl_cfg_s *_cfg, - void (*update)(struct rsnd_mod *mod), + void (*update)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod), const char * const *texts, u32 max);
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index bc122ed..67db696 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -876,9 +876,9 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod, return ret; }
-static void rsnd_src_reconvert_update(struct rsnd_mod *mod) +static void rsnd_src_reconvert_update(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); 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(io, src); @@ -931,7 +931,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, /* * enable sync convert */ - ret = rsnd_kctrl_new_s(mod, rtd, + ret = rsnd_kctrl_new_s(mod, io, rtd, rsnd_io_is_play(io) ? "SRC Out Rate Switch" : "SRC In Rate Switch", @@ -940,7 +940,7 @@ static int rsnd_src_pcm_new(struct rsnd_mod *mod, if (ret < 0) return ret;
- ret = rsnd_kctrl_new_s(mod, rtd, + ret = rsnd_kctrl_new_s(mod, io, rtd, rsnd_io_is_play(io) ? "SRC Out Rate" : "SRC In Rate",
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many paths if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. This patch checks module working status via io instead of mod
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 4 +--- sound/soc/sh/rcar/dma.c | 2 +- sound/soc/sh/rcar/rsnd.h | 3 +-- sound/soc/sh/rcar/src.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 266b24a..1eca85f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -196,10 +196,8 @@ void rsnd_mod_interrupt(struct rsnd_mod *mod, } }
-int rsnd_mod_is_working(struct rsnd_mod *mod) +int rsnd_io_is_working(struct rsnd_dai_stream *io) { - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); - /* see rsnd_dai_stream_init/quit() */ return !!io->substream; } diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 48b87bb..d306e29 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -52,7 +52,7 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod, */ spin_lock_irqsave(&priv->lock, flags);
- if (rsnd_mod_is_working(mod)) + if (rsnd_io_is_working(io)) elapsed = rsnd_dai_pointer_update(io, io->byte_per_period);
spin_unlock_irqrestore(&priv->lock, flags); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index fdb443b..756930b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -326,7 +326,6 @@ int rsnd_mod_init(struct rsnd_priv *priv, int id); void rsnd_mod_quit(struct rsnd_mod *mod); char *rsnd_mod_name(struct rsnd_mod *mod); -int rsnd_mod_is_working(struct rsnd_mod *mod); struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, struct rsnd_mod *mod); void rsnd_mod_interrupt(struct rsnd_mod *mod, @@ -356,7 +355,7 @@ struct rsnd_dai_stream { #define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io) #define rsnd_io_to_runtime(io) ((io)->substream ? \ (io)->substream->runtime : NULL) - +int rsnd_io_is_working(struct rsnd_dai_stream *io);
struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 67db696..c61c171 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -684,7 +684,7 @@ static void __rsnd_src_interrupt_gen2(struct rsnd_mod *mod, spin_lock(&priv->lock);
/* ignore all cases if not working */ - if (!rsnd_mod_is_working(mod)) + if (!rsnd_io_is_working(io)) goto rsnd_src_interrupt_gen2_out;
if (rsnd_src_error_record_gen2(mod)) { diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index fa1f2e5..2fbe59f 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -432,7 +432,7 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, spin_lock(&priv->lock);
/* ignore all cases if not working */ - if (!rsnd_mod_is_working(mod)) + if (!rsnd_io_is_working(io)) goto rsnd_ssi_interrupt_out;
status = rsnd_mod_read(mod, SSISR);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Each Renesas sound mod (= SSI/SRC/DVC) might be called from many path if it supports MIXer. In such case, mod <-> io is no longer 1:1 relationship. rsnd_mod_to_io() is no longer needed. Let's remove it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Tested-by: Keita Kobayashi keita.kobayashi.ym@renesas.com --- sound/soc/sh/rcar/core.c | 2 -- sound/soc/sh/rcar/rsnd.h | 2 -- 2 files changed, 4 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1eca85f..f1e5920 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -288,7 +288,6 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, }
io->mod[mod->type] = mod; - mod->io = io;
return 0; } @@ -296,7 +295,6 @@ static int rsnd_dai_connect(struct rsnd_mod *mod, static void rsnd_dai_disconnect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { - mod->io = NULL; io->mod[mod->type] = NULL; }
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 756930b..09fcc54 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -262,7 +262,6 @@ struct rsnd_mod { enum rsnd_mod_type type; struct rsnd_mod_ops *ops; struct rsnd_dma dma; - struct rsnd_dai_stream *io; struct rsnd_priv *priv; struct clk *clk; u32 status; @@ -313,7 +312,6 @@ struct rsnd_mod {
#define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_dma(mod) (&(mod)->dma) -#define rsnd_mod_to_io(mod) ((mod)->io) #define rsnd_mod_id(mod) ((mod)->id) #define rsnd_mod_hw_start(mod) clk_enable((mod)->clk) #define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk)
participants (2)
-
Kuninori Morimoto
-
Mark Brown