提交 30659894 编写于 作者: M Mark Brown

Merge tag 'asoc-v3.15-4' into asoc-linus

ASoC: Final updates for v3.15 merge window

A few more updates from last week - use of the tdm_slot mapping from
Xiubo plus a few smaller fixes and cleanups.

# gpg: Signature made Mon 31 Mar 2014 10:49:42 BST using RSA key ID 7EA229BD
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg:                 aka "Mark Brown <broonie@debian.org>"
# gpg:                 aka "Mark Brown <broonie@kernel.org>"
# gpg:                 aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg:                 aka "Mark Brown <broonie@linaro.org>"
# gpg:                 aka "Mark Brown <Mark.Brown@linaro.org>"
...@@ -7,14 +7,23 @@ Required properties: ...@@ -7,14 +7,23 @@ Required properties:
required register is required register is
SRU/ADG/SSI if generation1 SRU/ADG/SSI if generation1
SRU/ADG/SSIU/SSI if generation2 SRU/ADG/SSIU/SSI if generation2
- rcar_sound,ssi : SSI subnode - rcar_sound,ssi : Should contain SSI feature.
- rcar_sound,scu : SCU subnode The number of SSI subnode should be same as HW.
- rcar_sound,dai : DAI subnode see below for detail.
- rcar_sound,src : Should contain SRC feature.
The number of SRC subnode should be same as HW.
see below for detail.
- rcar_sound,dai : DAI contents.
The number of DAI subnode should be same as HW.
see below for detail.
SSI subnode properties: SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer - interrupts : Should contain SSI interrupt for PIO transfer
- shared-pin : if shared clock pin - shared-pin : if shared clock pin
SRC subnode properties:
no properties at this point
DAI subnode properties: DAI subnode properties:
- playback : list of playback modules - playback : list of playback modules
- capture : list of capture modules - capture : list of capture modules
......
...@@ -23,6 +23,11 @@ Optional properties: ...@@ -23,6 +23,11 @@ Optional properties:
Required subnodes: Required subnodes:
- simple-audio-card,dai-link : container for the CPU and CODEC sub-nodes
This container may be omitted when the
card has only one DAI link.
See the examples.
- simple-audio-card,cpu : CPU sub-node - simple-audio-card,cpu : CPU sub-node
- simple-audio-card,codec : CODEC sub-node - simple-audio-card,codec : CODEC sub-node
...@@ -49,7 +54,7 @@ Note: ...@@ -49,7 +54,7 @@ Note:
CPU and CODEC sides as we need to keep the settings identical for both ends CPU and CODEC sides as we need to keep the settings identical for both ends
of the link. of the link.
Example: Example 1 - single DAI link:
sound { sound {
compatible = "simple-audio-card"; compatible = "simple-audio-card";
...@@ -94,3 +99,38 @@ sh_fsi2: sh_fsi2@ec230000 { ...@@ -94,3 +99,38 @@ sh_fsi2: sh_fsi2@ec230000 {
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
interrupts = <0 146 0x4>; interrupts = <0 146 0x4>;
}; };
Example 2 - many DAI links:
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "Cubox Audio";
simple-audio-card,format = "i2s";
simple-audio-card,dai-link@0 { /* I2S - HDMI */
simple-audio-card,cpu {
sound-dai = <&audio1 0>;
};
simple-audio-card,codec {
sound-dai = <&tda998x 0>;
};
};
simple-audio-card,dai-link@1 { /* S/PDIF - HDMI */
simple-audio-card,cpu {
sound-dai = <&audio1 1>;
};
simple-audio-card,codec {
sound-dai = <&tda998x 1>;
};
};
simple-audio-card,dai-link@2 { /* S/PDIF - S/PDIF */
simple-audio-card,cpu {
sound-dai = <&audio1 1>;
};
simple-audio-card,codec {
sound-dai = <&spdif_codec>;
};
};
};
...@@ -429,14 +429,12 @@ static struct asoc_simple_card_info rsnd_card_info[] = { ...@@ -429,14 +429,12 @@ static struct asoc_simple_card_info rsnd_card_info[] = {
.card = "SSI56-AK4643", .card = "SSI56-AK4643",
.codec = "ak4642-codec.0-0012", .codec = "ak4642-codec.0-0012",
.platform = "rcar_sound", .platform = "rcar_sound",
.daifmt = SND_SOC_DAIFMT_LEFT_J, .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM,
.cpu_dai = { .cpu_dai = {
.name = "rsnd-dai.0", .name = "rsnd-dai.0",
.fmt = SND_SOC_DAIFMT_CBS_CFS,
}, },
.codec_dai = { .codec_dai = {
.name = "ak4642-hifi", .name = "ak4642-hifi",
.fmt = SND_SOC_DAIFMT_CBM_CFM,
.sysclk = 11289600, .sysclk = 11289600,
}, },
}, },
...@@ -446,10 +444,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { ...@@ -446,10 +444,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = {
.card = "SSI3-AK4554(playback)", .card = "SSI3-AK4554(playback)",
.codec = "ak4554-adc-dac.0", .codec = "ak4554-adc-dac.0",
.platform = "rcar_sound", .platform = "rcar_sound",
.daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J,
.cpu_dai = { .cpu_dai = {
.name = "rsnd-dai.1", .name = "rsnd-dai.1",
.fmt = SND_SOC_DAIFMT_CBM_CFM |
SND_SOC_DAIFMT_RIGHT_J,
}, },
.codec_dai = { .codec_dai = {
.name = "ak4554-hifi", .name = "ak4554-hifi",
...@@ -461,10 +458,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { ...@@ -461,10 +458,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = {
.card = "SSI4-AK4554(capture)", .card = "SSI4-AK4554(capture)",
.codec = "ak4554-adc-dac.0", .codec = "ak4554-adc-dac.0",
.platform = "rcar_sound", .platform = "rcar_sound",
.daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J,
.cpu_dai = { .cpu_dai = {
.name = "rsnd-dai.2", .name = "rsnd-dai.2",
.fmt = SND_SOC_DAIFMT_CBM_CFM |
SND_SOC_DAIFMT_LEFT_J,
}, },
.codec_dai = { .codec_dai = {
.name = "ak4554-hifi", .name = "ak4554-hifi",
...@@ -476,10 +472,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { ...@@ -476,10 +472,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = {
.card = "SSI7-AK4554(playback)", .card = "SSI7-AK4554(playback)",
.codec = "ak4554-adc-dac.1", .codec = "ak4554-adc-dac.1",
.platform = "rcar_sound", .platform = "rcar_sound",
.daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_RIGHT_J,
.cpu_dai = { .cpu_dai = {
.name = "rsnd-dai.3", .name = "rsnd-dai.3",
.fmt = SND_SOC_DAIFMT_CBM_CFM |
SND_SOC_DAIFMT_RIGHT_J,
}, },
.codec_dai = { .codec_dai = {
.name = "ak4554-hifi", .name = "ak4554-hifi",
...@@ -491,10 +486,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = { ...@@ -491,10 +486,9 @@ static struct asoc_simple_card_info rsnd_card_info[] = {
.card = "SSI8-AK4554(capture)", .card = "SSI8-AK4554(capture)",
.codec = "ak4554-adc-dac.1", .codec = "ak4554-adc-dac.1",
.platform = "rcar_sound", .platform = "rcar_sound",
.daifmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_LEFT_J,
.cpu_dai = { .cpu_dai = {
.name = "rsnd-dai.4", .name = "rsnd-dai.4",
.fmt = SND_SOC_DAIFMT_CBM_CFM |
SND_SOC_DAIFMT_LEFT_J,
}, },
.codec_dai = { .codec_dai = {
.name = "ak4554-hifi", .name = "ak4554-hifi",
......
...@@ -142,7 +142,7 @@ struct snd_soc_dai_ops { ...@@ -142,7 +142,7 @@ struct snd_soc_dai_ops {
* Called by soc_card drivers, normally in their hw_params. * Called by soc_card drivers, normally in their hw_params.
*/ */
int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); 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); unsigned int *tx_mask, unsigned int *rx_mask);
int (*set_tdm_slot)(struct snd_soc_dai *dai, int (*set_tdm_slot)(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask, unsigned int tx_mask, unsigned int rx_mask,
......
...@@ -13,6 +13,7 @@ config SND_SOC_FSL_SPDIF ...@@ -13,6 +13,7 @@ config SND_SOC_FSL_SPDIF
config SND_SOC_FSL_ESAI config SND_SOC_FSL_ESAI
tristate tristate
select REGMAP_MMIO select REGMAP_MMIO
select SND_SOC_FSL_UTILS
config SND_SOC_FSL_UTILS config SND_SOC_FSL_UTILS
tristate tristate
...@@ -120,6 +121,7 @@ if SND_IMX_SOC ...@@ -120,6 +121,7 @@ if SND_IMX_SOC
config SND_SOC_IMX_SSI config SND_SOC_IMX_SSI
tristate tristate
select SND_SOC_FSL_UTILS
config SND_SOC_IMX_PCM_FIQ config SND_SOC_IMX_PCM_FIQ
tristate tristate
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "fsl_esai.h" #include "fsl_esai.h"
#include "imx-pcm.h" #include "imx-pcm.h"
#include "fsl_utils.h"
#define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000 #define FSL_ESAI_RATES SNDRV_PCM_RATE_8000_192000
#define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ #define FSL_ESAI_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
...@@ -581,6 +582,7 @@ static struct snd_soc_dai_ops fsl_esai_dai_ops = { ...@@ -581,6 +582,7 @@ static struct snd_soc_dai_ops fsl_esai_dai_ops = {
.hw_params = fsl_esai_hw_params, .hw_params = fsl_esai_hw_params,
.set_sysclk = fsl_esai_set_dai_sysclk, .set_sysclk = fsl_esai_set_dai_sysclk,
.set_fmt = fsl_esai_set_dai_fmt, .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, .set_tdm_slot = fsl_esai_set_dai_tdm_slot,
}; };
......
...@@ -86,6 +86,33 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, ...@@ -86,6 +86,33 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np,
} }
EXPORT_SYMBOL(fsl_asoc_get_dma_channel); 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 <timur@freescale.com>"); MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Freescale ASoC utility code"); MODULE_DESCRIPTION("Freescale ASoC utility code");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -22,5 +22,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, const char *name, ...@@ -22,5 +22,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, const char *name,
struct snd_soc_dai_link *dai, struct snd_soc_dai_link *dai,
unsigned int *dma_channel_id, unsigned int *dma_channel_id,
unsigned int *dma_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 */ #endif /* _FSL_UTILS_H */
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/platform_data/asoc-imx-ssi.h> #include <linux/platform_data/asoc-imx-ssi.h>
#include "imx-ssi.h" #include "imx-ssi.h"
#include "fsl_utils.h"
#define SSI_SACNT_DEFAULT (SSI_SACNT_AC97EN | SSI_SACNT_FV) #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 = { ...@@ -339,6 +340,7 @@ static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
.set_fmt = imx_ssi_set_dai_fmt, .set_fmt = imx_ssi_set_dai_fmt,
.set_clkdiv = imx_ssi_set_dai_clkdiv, .set_clkdiv = imx_ssi_set_dai_clkdiv,
.set_sysclk = imx_ssi_set_dai_sysclk, .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, .set_tdm_slot = imx_ssi_set_dai_tdm_slot,
.trigger = imx_ssi_trigger, .trigger = imx_ssi_trigger,
}; };
......
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
struct simple_card_data { struct simple_card_data {
struct snd_soc_card snd_card; struct snd_soc_card snd_card;
struct asoc_simple_dai cpu_dai; struct simple_dai_props {
struct asoc_simple_dai codec_dai; struct asoc_simple_dai cpu_dai;
struct snd_soc_dai_link snd_link; 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, static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
...@@ -68,13 +70,16 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) ...@@ -68,13 +70,16 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_card_get_drvdata(rtd->card); snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *codec = rtd->codec_dai; struct snd_soc_dai *codec = rtd->codec_dai;
struct snd_soc_dai *cpu = rtd->cpu_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->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) if (ret < 0)
return ret; return ret;
ret = __asoc_simple_card_dai_init(cpu, &priv->cpu_dai); ret = __asoc_simple_card_dai_init(cpu, &dai_props->cpu_dai);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -146,13 +151,47 @@ asoc_simple_card_sub_parse_of(struct device_node *np, ...@@ -146,13 +151,47 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
return 0; 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, static int asoc_simple_card_parse_of(struct device_node *node,
struct simple_card_data *priv, 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 snd_soc_dai_link *dai_link = priv->snd_card.dai_link;
struct asoc_simple_dai *codec_dai = &priv->codec_dai; struct simple_dai_props *dai_props = priv->dai_props;
struct asoc_simple_dai *cpu_dai = &priv->cpu_dai;
struct device_node *np; struct device_node *np;
char *name; char *name;
unsigned int daifmt; unsigned int daifmt;
...@@ -181,78 +220,71 @@ static int asoc_simple_card_parse_of(struct device_node *node, ...@@ -181,78 +220,71 @@ static int asoc_simple_card_parse_of(struct device_node *node,
return ret; return ret;
} }
/* CPU sub-node */ /* loop on the DAI links */
ret = -EINVAL; np = NULL;
np = of_get_child_by_name(node, "simple-audio-card,cpu"); for (;;) {
if (np) { if (multi) {
ret = asoc_simple_card_sub_parse_of(np, daifmt, np = of_get_next_child(node, np);
cpu_dai, if (!np)
&dai_link->cpu_of_node, break;
&dai_link->cpu_dai_name); }
of_node_put(np);
}
if (ret < 0)
return ret;
/* CODEC sub-node */ ret = simple_card_cpu_codec_of(multi ? np : node,
ret = -EINVAL; daifmt, dai_link, dai_props);
np = of_get_child_by_name(node, "simple-audio-card,codec"); if (ret < 0)
if (np) { goto err;
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;
/* /*
* overwrite cpu_dai->fmt as its DAIFMT_MASTER bit is based on CODEC * 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. * while the other bits should be identical unless buggy SW/HW design.
*/ */
cpu_dai->fmt = codec_dai->fmt; 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;
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 (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) if (!multi)
return -EINVAL; break;
dai_link++;
dai_props++;
}
/* card name is created from CPU/CODEC dai name */ /* card name is created from CPU/CODEC dai name */
name = devm_kzalloc(dev, dai_link = priv->snd_card.dai_link;
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);
if (!priv->snd_card.name) if (!priv->snd_card.name)
priv->snd_card.name = name; priv->snd_card.name = dai_link->name;
dai_link->name = dai_link->stream_name = name;
/* simple-card assumes platform == cpu */
dai_link->platform_of_node = dai_link->cpu_of_node;
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); dev_dbg(dev, "platform : %04x\n", daifmt);
dai_props = priv->dai_props;
dev_dbg(dev, "cpu : %s / %04x / %d\n", dev_dbg(dev, "cpu : %s / %04x / %d\n",
dai_link->cpu_dai_name, dai_link->cpu_dai_name,
cpu_dai->fmt, dai_props->cpu_dai.fmt,
cpu_dai->sysclk); dai_props->cpu_dai.sysclk);
dev_dbg(dev, "codec : %s / %04x / %d\n", dev_dbg(dev, "codec : %s / %04x / %d\n",
dai_link->codec_dai_name, dai_link->codec_dai_name,
codec_dai->fmt, dai_props->codec_dai.fmt,
codec_dai->sysclk); dai_props->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;
return 0; return 0;
err:
of_node_put(np);
return ret;
} }
/* update the reference count of the devices nodes at end of probe */ /* update the reference count of the devices nodes at end of probe */
...@@ -282,9 +314,21 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -282,9 +314,21 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev; 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;
}
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) * num_links,
GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
...@@ -293,18 +337,38 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -293,18 +337,38 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
*/ */
priv->snd_card.owner = THIS_MODULE; priv->snd_card.owner = THIS_MODULE;
priv->snd_card.dev = dev; 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.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) * num_links,
GFP_KERNEL);
if (!priv->dai_props)
return -ENOMEM;
if (np && of_device_is_available(np)) { 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 < 0) {
if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER)
dev_err(dev, "parse error %d\n", ret); dev_err(dev, "parse error %d\n", ret);
goto err; 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 { } else {
struct asoc_simple_card_info *cinfo; struct asoc_simple_card_info *cinfo;
...@@ -330,13 +394,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev) ...@@ -330,13 +394,13 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
dai_link->codec_name = cinfo->codec; dai_link->codec_name = cinfo->codec;
dai_link->cpu_dai_name = cinfo->cpu_dai.name; dai_link->cpu_dai_name = cinfo->cpu_dai.name;
dai_link->codec_dai_name = cinfo->codec_dai.name; dai_link->codec_dai_name = cinfo->codec_dai.name;
memcpy(&priv->cpu_dai, &cinfo->cpu_dai, memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
sizeof(priv->cpu_dai)); sizeof(priv->dai_props->cpu_dai));
memcpy(&priv->codec_dai, &cinfo->codec_dai, memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
sizeof(priv->codec_dai)); sizeof(priv->dai_props->codec_dai));
priv->cpu_dai.fmt |= cinfo->daifmt; priv->dai_props->cpu_dai.fmt |= cinfo->daifmt;
priv->codec_dai.fmt |= cinfo->daifmt; priv->dai_props->codec_dai.fmt |= cinfo->daifmt;
} }
/* /*
......
...@@ -182,16 +182,20 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, ...@@ -182,16 +182,20 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
struct rsnd_dai_stream *io, struct rsnd_dai_stream *io,
struct snd_pcm_runtime *runtime) struct snd_pcm_runtime *runtime)
{ {
struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
struct rsnd_src *src; 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) if (!rate)
rate = runtime->rate; rate = runtime->rate;
......
...@@ -1253,7 +1253,7 @@ static int soc_post_component_init(struct snd_soc_card *card, ...@@ -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_dai_link *dai_link = NULL;
struct snd_soc_aux_dev *aux_dev = NULL; struct snd_soc_aux_dev *aux_dev = NULL;
struct snd_soc_pcm_runtime *rtd; struct snd_soc_pcm_runtime *rtd;
const char *temp, *name; const char *name;
int ret = 0; int ret = 0;
if (!dailess) { if (!dailess) {
...@@ -1267,10 +1267,6 @@ static int soc_post_component_init(struct snd_soc_card *card, ...@@ -1267,10 +1267,6 @@ static int soc_post_component_init(struct snd_soc_card *card,
} }
rtd->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 */ /* do machine specific initialization */
if (!dailess && dai_link->init) if (!dailess && dai_link->init)
ret = dai_link->init(rtd); ret = dai_link->init(rtd);
...@@ -1280,7 +1276,6 @@ static int soc_post_component_init(struct snd_soc_card *card, ...@@ -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); dev_err(card->dev, "ASoC: failed to init %s: %d\n", name, ret);
return ret; return ret;
} }
codec->name_prefix = temp;
/* register the rtd device */ /* register the rtd device */
rtd->codec = codec; rtd->codec = codec;
...@@ -3625,14 +3620,14 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ...@@ -3625,14 +3620,14 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
EXPORT_SYMBOL_GPL(snd_soc_dai_set_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. * @slots: Number of slots in use.
* @tx_mask: bitmask representing active TX slots. * @tx_mask: bitmask representing active TX slots.
* @rx_mask: bitmask representing active RX slots. * @rx_mask: bitmask representing active RX slots.
* *
* Generates the TDM tx and rx slot default masks for DAI. * 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 *tx_mask,
unsigned int *rx_mask) unsigned int *rx_mask)
{ {
...@@ -3662,11 +3657,11 @@ static int snd_soc_of_xlate_tdm_slot_mask(unsigned int slots, ...@@ -3662,11 +3657,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, 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) unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
{ {
if (dai->driver && dai->driver->ops->of_xlate_tdm_slot_mask) if (dai->driver && dai->driver->ops->xlate_tdm_slot_mask)
dai->driver->ops->of_xlate_tdm_slot_mask(slots, dai->driver->ops->xlate_tdm_slot_mask(slots,
&tx_mask, &rx_mask); &tx_mask, &rx_mask);
else 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) if (dai->driver && dai->driver->ops->set_tdm_slot)
return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <sound/soc.h> #include <sound/soc.h>
#include <sound/dmaengine_pcm.h> #include <sound/dmaengine_pcm.h>
#include "tegra_asoc_utils.h"
#include "tegra20_ac97.h" #include "tegra20_ac97.h"
#define DRV_NAME "tegra20-ac97" #define DRV_NAME "tegra20-ac97"
...@@ -376,18 +375,10 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ...@@ -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.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ac97->playback_dma_data.maxburst = 4; 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); ret = clk_prepare_enable(ac97->clk_ac97);
if (ret) { if (ret) {
dev_err(&pdev->dev, "clk_enable failed: %d\n", 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); ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops);
...@@ -419,8 +410,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ...@@ -419,8 +410,6 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
snd_soc_unregister_component(&pdev->dev); snd_soc_unregister_component(&pdev->dev);
err_clk_disable_unprepare: err_clk_disable_unprepare:
clk_disable_unprepare(ac97->clk_ac97); clk_disable_unprepare(ac97->clk_ac97);
err_asoc_utils_fini:
tegra_asoc_utils_fini(&ac97->util_data);
err_clk_put: err_clk_put:
err: err:
snd_soc_set_ac97_ops(NULL); snd_soc_set_ac97_ops(NULL);
...@@ -434,8 +423,6 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) ...@@ -434,8 +423,6 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev)
tegra_pcm_platform_unregister(&pdev->dev); tegra_pcm_platform_unregister(&pdev->dev);
snd_soc_unregister_component(&pdev->dev); snd_soc_unregister_component(&pdev->dev);
tegra_asoc_utils_fini(&ac97->util_data);
clk_disable_unprepare(ac97->clk_ac97); clk_disable_unprepare(ac97->clk_ac97);
snd_soc_set_ac97_ops(NULL); snd_soc_set_ac97_ops(NULL);
......
...@@ -90,6 +90,5 @@ struct tegra20_ac97 { ...@@ -90,6 +90,5 @@ struct tegra20_ac97 {
struct regmap *regmap; struct regmap *regmap;
int reset_gpio; int reset_gpio;
int sync_gpio; int sync_gpio;
struct tegra_asoc_utils_data util_data;
}; };
#endif /* __TEGRA20_AC97_H__ */ #endif /* __TEGRA20_AC97_H__ */
...@@ -29,10 +29,13 @@ ...@@ -29,10 +29,13 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "tegra_asoc_utils.h"
#define DRV_NAME "tegra-snd-wm9712" #define DRV_NAME "tegra-snd-wm9712"
struct tegra_wm9712 { struct tegra_wm9712 {
struct platform_device *codec; struct platform_device *codec;
struct tegra_asoc_utils_data util_data;
}; };
static const struct snd_soc_dapm_widget tegra_wm9712_dapm_widgets[] = { 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) ...@@ -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; 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); ret = snd_soc_register_card(card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret); ret);
goto codec_unregister; goto asoc_utils_fini;
} }
return 0; return 0;
asoc_utils_fini:
tegra_asoc_utils_fini(&machine->util_data);
codec_unregister: codec_unregister:
platform_device_del(machine->codec); platform_device_del(machine->codec);
codec_put: codec_put:
...@@ -141,6 +154,8 @@ static int tegra_wm9712_driver_remove(struct platform_device *pdev) ...@@ -141,6 +154,8 @@ static int tegra_wm9712_driver_remove(struct platform_device *pdev)
snd_soc_unregister_card(card); snd_soc_unregister_card(card);
tegra_asoc_utils_fini(&machine->util_data);
platform_device_unregister(machine->codec); platform_device_unregister(machine->codec);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册