From b1eac430b6a4bee6821273d9b41dd3593eb7830b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 23 Mar 2014 21:23:42 -0700 Subject: ASoC: rcar: bugfix: it cares about the non-src case src might not exist. kernel will be hung-up without this patch in such case. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/src.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index eee75ebf961c..6232b7d307aa 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -182,16 +182,20 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime) { + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); struct rsnd_src *src; - unsigned int rate; + unsigned int rate = 0; - src = rsnd_mod_to_src(rsnd_io_to_mod_src(io)); + if (src_mod) { + src = rsnd_mod_to_src(src_mod); + + /* + * return convert rate if SRC is used, + * otherwise, return runtime->rate as usual + */ + rate = rsnd_src_convert_rate(src); + } - /* - * return convert rate if SRC is used, - * otherwise, return runtime->rate as usual - */ - rate = rsnd_src_convert_rate(src); if (!rate) rate = runtime->rate; -- cgit v1.2.3 From 6479f15ad7227da99b4bfc2a465cc50a28ff1b5a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 12 Mar 2014 15:27:40 +0100 Subject: ASoC: Remove name_prefix unset during DAI link init hack Before we had card level support for DAPM and controls machine drivers would register their controls and DAPM elements with the CODEC. This required us to temporarily unset the name_prefix of a CODEC during the rtd init callback to avoid the machine level controls getting the CODEC's prefix. Now that all machine drivers properly register their machine level controls and DAPM elements with the card rather than with the CODEC we can drop the hack that sets the CODEC's name_prefix to NULL while calling the DAI link or AUX dev init callback. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b322cf294d06..daca4b7de45c 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1253,7 +1253,7 @@ static int soc_post_component_init(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link = NULL; struct snd_soc_aux_dev *aux_dev = NULL; struct snd_soc_pcm_runtime *rtd; - const char *temp, *name; + const char *name; int ret = 0; if (!dailess) { @@ -1267,10 +1267,6 @@ static int soc_post_component_init(struct snd_soc_card *card, } rtd->card = card; - /* machine controls, routes and widgets are not prefixed */ - temp = codec->name_prefix; - codec->name_prefix = NULL; - /* do machine specific initialization */ if (!dailess && dai_link->init) ret = dai_link->init(rtd); @@ -1280,7 +1276,6 @@ static int soc_post_component_init(struct snd_soc_card *card, dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret); return ret; } - codec->name_prefix = temp; /* register the rtd device */ rtd->codec = codec; -- cgit v1.2.3 From e5c2151483facbe1a67b12ec881f45ae25b54c21 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 21 Mar 2014 14:17:12 +0800 Subject: ASoC: core: remove the 'of_' prefix of of_xlate_tdm_slot_mask. The 'of_' is not appropriate here for there hasn't any DT parsing. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 2 +- sound/soc/soc-core.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 2f66d5e8cd15..fad76769f153 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -142,7 +142,7 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); - int (*of_xlate_tdm_slot_mask)(unsigned int slots, + int (*xlate_tdm_slot_mask)(unsigned int slots, unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b322cf294d06..318fee8093ce 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3625,14 +3625,14 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); /** - * snd_soc_of_xlate_tdm_slot - generate tx/rx slot mask. + * snd_soc_xlate_tdm_slot - generate tx/rx slot mask. * @slots: Number of slots in use. * @tx_mask: bitmask representing active TX slots. * @rx_mask: bitmask representing active RX slots. * * Generates the TDM tx and rx slot default masks for DAI. */ -static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, +static int snd_soc_xlate_tdm_slot_mask(unsigned int slots, unsigned int *tx_mask, unsigned int *rx_mask) { @@ -3662,11 +3662,11 @@ static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { - if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) - dai->driver->ops->of_xlate_tdm_slot_mask(slots, + if (dai->driver && dai->driver->ops->xlate_tdm_slot_mask) + dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); else - snd_soc_of_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); if (dai->driver && dai->driver->ops->set_tdm_slot) return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, -- cgit v1.2.3 From 82535314a942c1235d54a0cdbe48d38f640d56ba Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 21 Mar 2014 14:17:13 +0800 Subject: ASoC: fsl-utils: Add fsl_asoc_xlate_tdm_slot_mask() support. This patch add fsl_asoc_xlate_tdm_slot_mask() support for utils. For the some spcified DAI driver, this will be used to generate the TDM slot TX/RX mask. And the TX/RX mask will use a 0 bit for an active slot as default, and the default active bits are at the LSB of the masks. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_utils.c | 27 +++++++++++++++++++++++++++ sound/soc/fsl/fsl_utils.h | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index b9e42b503a37..2ac7755da876 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c @@ -86,6 +86,33 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, } EXPORT_SYMBOL(fsl_asoc_get_dma_channel); +/** + * fsl_asoc_xlate_tdm_slot_mask - generate TDM slot TX/RX mask. + * + * @slots: Number of slots in use. + * @tx_mask: bitmask representing active TX slots. + * @rx_mask: bitmask representing active RX slots. + * + * This function used to generate the TDM slot TX/RX mask. And the TX/RX + * mask will use a 0 bit for an active slot as default, and the default + * active bits are at the LSB of the mask value. + */ +int fsl_asoc_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask) +{ + if (!slots) + return -EINVAL; + + if (tx_mask) + *tx_mask = ~((1 << slots) - 1); + if (rx_mask) + *rx_mask = ~((1 << slots) - 1); + + return 0; +} +EXPORT_SYMBOL_GPL(fsl_asoc_xlate_tdm_slot_mask); + MODULE_AUTHOR("Timur Tabi "); MODULE_DESCRIPTION("Freescale ASoC utility code"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/fsl_utils.h b/sound/soc/fsl/fsl_utils.h index b2951126527c..df535db40313 100644 --- a/sound/soc/fsl/fsl_utils.h +++ b/sound/soc/fsl/fsl_utils.h @@ -22,5 +22,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, const char *name, struct snd_soc_dai_link *dai, unsigned int *dma_channel_id, unsigned int *dma_id); - +int fsl_asoc_xlate_tdm_slot_mask(unsigned int slots, + unsigned int *tx_mask, + unsigned int *rx_mask); #endif /* _FSL_UTILS_H */ -- cgit v1.2.3 From a603c8ee526f5ea9ad9b40710308766299ad8a69 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 21 Mar 2014 14:17:14 +0800 Subject: ASoC: fsl-esai: Add .xlate_tdm_slot_mask() support. This patch add .xlate_tdm_slot_mask support for ESAI, and this will generate the TDM slot TX and RX masks. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 1 + sound/soc/fsl/fsl_esai.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 597962ec28fa..789bc4dd5f4f 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -13,6 +13,7 @@ config SND_SOC_FSL_SPDIF config SND_SOC_FSL_ESAI tristate select REGMAP_MMIO + select SND_SOC_FSL_UTILS config SND_SOC_FSL_UTILS tristate diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 0ba37005ab04..c8e5db1414d7 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -18,6 +18,7 @@ #include "fsl_esai.h" #include "imx-pcm.h" +#include "fsl_utils.h" #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000 #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ @@ -581,6 +582,7 @@ static struct snd_soc_dai_ops fsl_esai_dai_ops = { .hw_params = fsl_esai_hw_params, .set_sysclk = fsl_esai_set_dai_sysclk, .set_fmt = fsl_esai_set_dai_fmt, + .xlate_tdm_slot_mask = fsl_asoc_xlate_tdm_slot_mask, .set_tdm_slot = fsl_esai_set_dai_tdm_slot, }; -- cgit v1.2.3 From 5f9e6ff66f49d4d791af2b7c9d20727fb8a688e8 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 21 Mar 2014 14:17:15 +0800 Subject: ASoC: imx-ssi: Add .xlate_tdm_slot_mask() support. This patch add .xlate_tdm_slot_mask support for IMX SSI, and this will generate the TDM slot TX and RX masks. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 1 + sound/soc/fsl/imx-ssi.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 789bc4dd5f4f..338a91642471 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -121,6 +121,7 @@ if SND_IMX_SOC config SND_SOC_IMX_SSI tristate + select SND_SOC_FSL_UTILS config SND_SOC_IMX_PCM_FIQ tristate diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index df552fa1aa65..ab2fdd76b693 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -50,6 +50,7 @@ #include #include "imx-ssi.h" +#include "fsl_utils.h" #define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) @@ -339,6 +340,7 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { .set_fmt = imx_ssi_set_dai_fmt, .set_clkdiv = imx_ssi_set_dai_clkdiv, .set_sysclk = imx_ssi_set_dai_sysclk, + .xlate_tdm_slot_mask = fsl_asoc_xlate_tdm_slot_mask, .set_tdm_slot = imx_ssi_set_dai_tdm_slot, .trigger = imx_ssi_trigger, }; -- cgit v1.2.3 From cf7dc23cbfd5c4c5ab2136f19522d9b3b41acf99 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 20 Mar 2014 10:52:41 +0100 Subject: ASoC: simple-card: dynamically allocate the DAI link and properties The DAI link array and the properties (fmt, sysclk slots) are hard-coded for a single CPU / CODEC link. This patch dynamically allocates the DAI link array and the properties with the aim of supporting many DAI links. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 42 ++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'sound') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2ee8ed56bcf1..1e865c5d377f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -20,9 +20,11 @@ struct simple_card_data { struct snd_soc_card snd_card; - struct asoc_simple_dai cpu_dai; - struct asoc_simple_dai codec_dai; - struct snd_soc_dai_link snd_link; + struct simple_dai_props { + struct asoc_simple_dai cpu_dai; + struct asoc_simple_dai codec_dai; + } *dai_props; + struct snd_soc_dai_link dai_link[]; /* dynamically allocated */ }; static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai, @@ -70,11 +72,11 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *cpu = rtd->cpu_dai; int ret; - ret = __asoc_simple_card_dai_init(codec, &priv->codec_dai); + ret = __asoc_simple_card_dai_init(codec, &priv->dai_props->codec_dai); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai); + ret = __asoc_simple_card_dai_init(cpu, &priv->dai_props->cpu_dai); if (ret < 0) return ret; @@ -151,8 +153,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, struct device *dev) { struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; - struct asoc_simple_dai *codec_dai = &priv->codec_dai; - struct asoc_simple_dai *cpu_dai = &priv->cpu_dai; + struct asoc_simple_dai *codec_dai = &priv->dai_props->codec_dai; + struct asoc_simple_dai *cpu_dai = &priv->dai_props->cpu_dai; struct device_node *np; char *name; unsigned int daifmt; @@ -284,7 +286,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int ret; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + /* allocate the private data and the DAI link array */ + priv = devm_kzalloc(dev, + sizeof(*priv) + sizeof(*dai_link), + GFP_KERNEL); if (!priv) return -ENOMEM; @@ -293,10 +298,17 @@ static int asoc_simple_card_probe(struct platform_device *pdev) */ priv->snd_card.owner = THIS_MODULE; priv->snd_card.dev = dev; - dai_link = &priv->snd_link; + dai_link = priv->dai_link; priv->snd_card.dai_link = dai_link; priv->snd_card.num_links = 1; + /* get room for the other properties */ + priv->dai_props = devm_kzalloc(dev, + sizeof(*priv->dai_props), + GFP_KERNEL); + if (!priv->dai_props) + return -ENOMEM; + if (np && of_device_is_available(np)) { ret = asoc_simple_card_parse_of(np, priv, dev); @@ -330,13 +342,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) dai_link->codec_name = cinfo->codec; dai_link->cpu_dai_name = cinfo->cpu_dai.name; dai_link->codec_dai_name = cinfo->codec_dai.name; - memcpy(&priv->cpu_dai, &cinfo->cpu_dai, - sizeof(priv->cpu_dai)); - memcpy(&priv->codec_dai, &cinfo->codec_dai, - sizeof(priv->codec_dai)); + memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai, + sizeof(priv->dai_props->cpu_dai)); + memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai, + sizeof(priv->dai_props->codec_dai)); - priv->cpu_dai.fmt |= cinfo->daifmt; - priv->codec_dai.fmt |= cinfo->daifmt; + priv->dai_props->cpu_dai.fmt |= cinfo->daifmt; + priv->dai_props->codec_dai.fmt |= cinfo->daifmt; } /* -- cgit v1.2.3 From 6a91a17bd7b92b2d2aa9ece85457f52a62fd7708 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 20 Mar 2014 11:49:55 +0100 Subject: ASoC: simple-card: Handle many DAI links Some simple audio cards may have many DAI links. This patch extends the simple-card driver for handling such cards. Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 190 +++++++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 69 deletions(-) (limited to 'sound') diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 1e865c5d377f..21f1ccbdf582 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -70,13 +70,16 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *cpu = rtd->cpu_dai; - int ret; + struct simple_dai_props *dai_props; + int num, ret; - ret = __asoc_simple_card_dai_init(codec, &priv->dai_props->codec_dai); + num = rtd - rtd->card->rtd; + dai_props = &priv->dai_props[num]; + ret = __asoc_simple_card_dai_init(codec, &dai_props->codec_dai); if (ret < 0) return ret; - ret = __asoc_simple_card_dai_init(cpu, &priv->dai_props->cpu_dai); + ret = __asoc_simple_card_dai_init(cpu, &dai_props->cpu_dai); if (ret < 0) return ret; @@ -148,13 +151,47 @@ asoc_simple_card_sub_parse_of(struct device_node *np, return 0; } +static int simple_card_cpu_codec_of(struct device_node *node, + int daifmt, + struct snd_soc_dai_link *dai_link, + struct simple_dai_props *dai_props) +{ + struct device_node *np; + int ret; + + /* CPU sub-node */ + ret = -EINVAL; + np = of_get_child_by_name(node, "simple-audio-card,cpu"); + if (np) { + ret = asoc_simple_card_sub_parse_of(np, daifmt, + &dai_props->cpu_dai, + &dai_link->cpu_of_node, + &dai_link->cpu_dai_name); + of_node_put(np); + } + if (ret < 0) + return ret; + + /* CODEC sub-node */ + ret = -EINVAL; + np = of_get_child_by_name(node, "simple-audio-card,codec"); + if (np) { + ret = asoc_simple_card_sub_parse_of(np, daifmt, + &dai_props->codec_dai, + &dai_link->codec_of_node, + &dai_link->codec_dai_name); + of_node_put(np); + } + return ret; +} + static int asoc_simple_card_parse_of(struct device_node *node, struct simple_card_data *priv, - struct device *dev) + struct device *dev, + int multi) { struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link; - struct asoc_simple_dai *codec_dai = &priv->dai_props->codec_dai; - struct asoc_simple_dai *cpu_dai = &priv->dai_props->cpu_dai; + struct simple_dai_props *dai_props = priv->dai_props; struct device_node *np; char *name; unsigned int daifmt; @@ -183,78 +220,71 @@ static int asoc_simple_card_parse_of(struct device_node *node, return ret; } - /* CPU sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,cpu"); - if (np) { - ret = asoc_simple_card_sub_parse_of(np, daifmt, - cpu_dai, - &dai_link->cpu_of_node, - &dai_link->cpu_dai_name); - of_node_put(np); - } - if (ret < 0) - return ret; + /* loop on the DAI links */ + np = NULL; + for (;;) { + if (multi) { + np = of_get_next_child(node, np); + if (!np) + break; + } - /* CODEC sub-node */ - ret = -EINVAL; - np = of_get_child_by_name(node, "simple-audio-card,codec"); - if (np) { - ret = asoc_simple_card_sub_parse_of(np, daifmt, - codec_dai, - &dai_link->codec_of_node, - &dai_link->codec_dai_name); - of_node_put(np); - } - if (ret < 0) - return ret; + ret = simple_card_cpu_codec_of(multi ? np : node, + daifmt, dai_link, dai_props); + if (ret < 0) + goto err; - /* - * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC - * while the other bits should be identical unless buggy SW/HW design. - */ - cpu_dai->fmt = codec_dai->fmt; + /* + * overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC + * while the other bits should be identical unless buggy SW/HW design. + */ + dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt; + + if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { + ret = -EINVAL; + goto err; + } + + /* simple-card assumes platform == cpu */ + dai_link->platform_of_node = dai_link->cpu_of_node; - if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) - return -EINVAL; + name = devm_kzalloc(dev, + strlen(dai_link->cpu_dai_name) + + strlen(dai_link->codec_dai_name) + 2, + GFP_KERNEL); + sprintf(name, "%s-%s", dai_link->cpu_dai_name, + dai_link->codec_dai_name); + dai_link->name = dai_link->stream_name = name; + + if (!multi) + break; + + dai_link++; + dai_props++; + } /* card 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); - sprintf(name, "%s-%s", dai_link->cpu_dai_name, - dai_link->codec_dai_name); + dai_link = priv->snd_card.dai_link; if (!priv->snd_card.name) - priv->snd_card.name = name; - dai_link->name = dai_link->stream_name = name; - - /* simple-card assumes platform == cpu */ - dai_link->platform_of_node = dai_link->cpu_of_node; + priv->snd_card.name = dai_link->name; - dev_dbg(dev, "card-name : %s\n", name); + dev_dbg(dev, "card-name : %s\n", priv->snd_card.name); dev_dbg(dev, "platform : %04x\n", daifmt); + dai_props = priv->dai_props; dev_dbg(dev, "cpu : %s / %04x / %d\n", dai_link->cpu_dai_name, - cpu_dai->fmt, - cpu_dai->sysclk); + dai_props->cpu_dai.fmt, + dai_props->cpu_dai.sysclk); dev_dbg(dev, "codec : %s / %04x / %d\n", dai_link->codec_dai_name, - codec_dai->fmt, - codec_dai->sysclk); - - /* - * 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 to escape name matching. - * see - * fmt_single_name() - * fmt_multiple_name() - */ - dai_link->cpu_dai_name = NULL; + dai_props->codec_dai.fmt, + dai_props->codec_dai.sysclk); return 0; + +err: + of_node_put(np); + return ret; } /* update the reference count of the devices nodes at end of probe */ @@ -284,11 +314,20 @@ static int asoc_simple_card_probe(struct platform_device *pdev) struct snd_soc_dai_link *dai_link; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; - int ret; + int num_links, multi, ret; + + /* get the number of DAI links */ + if (np && of_get_child_by_name(np, "simple-audio-card,dai-link")) { + num_links = of_get_child_count(np); + multi = 1; + } else { + num_links = 1; + multi = 0; + } /* allocate the private data and the DAI link array */ priv = devm_kzalloc(dev, - sizeof(*priv) + sizeof(*dai_link), + sizeof(*priv) + sizeof(*dai_link) * num_links, GFP_KERNEL); if (!priv) return -ENOMEM; @@ -300,23 +339,36 @@ static int asoc_simple_card_probe(struct platform_device *pdev) priv->snd_card.dev = dev; dai_link = priv->dai_link; priv->snd_card.dai_link = dai_link; - priv->snd_card.num_links = 1; + priv->snd_card.num_links = num_links; /* get room for the other properties */ priv->dai_props = devm_kzalloc(dev, - sizeof(*priv->dai_props), + sizeof(*priv->dai_props) * num_links, GFP_KERNEL); if (!priv->dai_props) return -ENOMEM; if (np && of_device_is_available(np)) { - ret = asoc_simple_card_parse_of(np, priv, dev); + ret = asoc_simple_card_parse_of(np, priv, dev, multi); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); goto err; } + + /* + * 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 to escape name matching. + * see + * fmt_single_name() + * fmt_multiple_name() + */ + if (num_links == 1) + dai_link->cpu_dai_name = NULL; + } else { struct asoc_simple_card_info *cinfo; -- cgit v1.2.3 From 1ca2e8474df3626f8d64d23420f8bd16bcef2448 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Tue, 18 Mar 2014 21:30:49 +0100 Subject: ASoC: tegra: move AC97 clock handling to the machine driver On Tegra the convention is to have a single machine driver that's controlling the whole audio subsystem. Move the clock handling to the machine driver, to be in line with the other Tegra drivers and give the machine driver full control over the single Tegra audio PLL. Signed-off-by: Lucas Stach Acked-by: Stephen Warren Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_ac97.c | 15 +-------------- sound/soc/tegra/tegra20_ac97.h | 1 - sound/soc/tegra/tegra_wm9712.c | 17 ++++++++++++++++- 3 files changed, 17 insertions(+), 16 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index cf5e1cfe818d..29f8832a79c4 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -37,7 +37,6 @@ #include #include -#include "tegra_asoc_utils.h" #include "tegra20_ac97.h" #define DRV_NAME "tegra20-ac97" @@ -376,18 +375,10 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ac97->playback_dma_data.maxburst = 4; - ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); - if (ret) - goto err_clk_put; - - ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); - if (ret) - goto err_asoc_utils_fini; - ret = clk_prepare_enable(ac97->clk_ac97); if (ret) { dev_err(&pdev->dev, "clk_enable failed: %d\n", ret); - goto err_asoc_utils_fini; + goto err; } ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); @@ -419,8 +410,6 @@ err_unregister_component: snd_soc_unregister_component(&pdev->dev); err_clk_disable_unprepare: clk_disable_unprepare(ac97->clk_ac97); -err_asoc_utils_fini: - tegra_asoc_utils_fini(&ac97->util_data); err_clk_put: err: snd_soc_set_ac97_ops(NULL); @@ -434,8 +423,6 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) tegra_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); - tegra_asoc_utils_fini(&ac97->util_data); - clk_disable_unprepare(ac97->clk_ac97); snd_soc_set_ac97_ops(NULL); diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h index 4acb3aaba29b..0a39d823edcb 100644 --- a/sound/soc/tegra/tegra20_ac97.h +++ b/sound/soc/tegra/tegra20_ac97.h @@ -90,6 +90,5 @@ struct tegra20_ac97 { struct regmap *regmap; int reset_gpio; int sync_gpio; - struct tegra_asoc_utils_data util_data; }; #endif /* __TEGRA20_AC97_H__ */ diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index 45b57892b6a5..25a7f8211ecf 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c @@ -29,10 +29,13 @@ #include #include +#include "tegra_asoc_utils.h" + #define DRV_NAME "tegra-snd-wm9712" struct tegra_wm9712 { struct platform_device *codec; + struct tegra_asoc_utils_data util_data; }; static const struct snd_soc_dapm_widget tegra_wm9712_dapm_widgets[] = { @@ -118,15 +121,25 @@ static int tegra_wm9712_driver_probe(struct platform_device *pdev) tegra_wm9712_dai.platform_of_node = tegra_wm9712_dai.cpu_of_node; + ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev); + if (ret) + goto codec_unregister; + + ret = tegra_asoc_utils_set_ac97_rate(&machine->util_data); + if (ret) + goto asoc_utils_fini; + ret = snd_soc_register_card(card); if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto codec_unregister; + goto asoc_utils_fini; } return 0; +asoc_utils_fini: + tegra_asoc_utils_fini(&machine->util_data); codec_unregister: platform_device_del(machine->codec); codec_put: @@ -141,6 +154,8 @@ static int tegra_wm9712_driver_remove(struct platform_device *pdev) snd_soc_unregister_card(card); + tegra_asoc_utils_fini(&machine->util_data); + platform_device_unregister(machine->codec); return 0; -- cgit v1.2.3