mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 22:51:42 +00:00
Merge branch 'asoc-5.7' into asoc-5.8
This commit is contained in:
commit
39400f34a2
@ -56,6 +56,9 @@ properties:
|
||||
- const: tx
|
||||
- const: rx
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
rockchip,capture-channels:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
@ -1,45 +0,0 @@
|
||||
* Rockchip SPDIF transceiver
|
||||
|
||||
The S/PDIF audio block is a stereo transceiver that allows the
|
||||
processor to receive and transmit digital audio via an coaxial cable or
|
||||
a fibre cable.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of the following:
|
||||
- "rockchip,rk3066-spdif"
|
||||
- "rockchip,rk3188-spdif"
|
||||
- "rockchip,rk3228-spdif"
|
||||
- "rockchip,rk3288-spdif"
|
||||
- "rockchip,rk3328-spdif"
|
||||
- "rockchip,rk3366-spdif"
|
||||
- "rockchip,rk3368-spdif"
|
||||
- "rockchip,rk3399-spdif"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: should contain the SPDIF interrupt.
|
||||
- dmas: DMA specifiers for tx dma. See the DMA client binding,
|
||||
Documentation/devicetree/bindings/dma/dma.txt
|
||||
- dma-names: should be "tx"
|
||||
- clocks: a list of phandle + clock-specifier pairs, one for each entry
|
||||
in clock-names.
|
||||
- clock-names: should contain following:
|
||||
- "hclk": clock for SPDIF controller
|
||||
- "mclk" : clock for SPDIF bus
|
||||
|
||||
Required properties on RK3288:
|
||||
- rockchip,grf: the phandle of the syscon node for the general register
|
||||
file (GRF)
|
||||
|
||||
Example for the rk3188 SPDIF controller:
|
||||
|
||||
spdif: spdif@1011e000 {
|
||||
compatible = "rockchip,rk3188-spdif", "rockchip,rk3066-spdif";
|
||||
reg = <0x1011e000 0x2000>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac1_s 8>;
|
||||
dma-names = "tx";
|
||||
clock-names = "hclk", "mclk";
|
||||
clocks = <&cru HCLK_SPDIF>, <&cru SCLK_SPDIF>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
101
Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
Normal file
101
Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
Normal file
@ -0,0 +1,101 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/rockchip-spdif.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip SPDIF transceiver
|
||||
|
||||
description:
|
||||
The S/PDIF audio block is a stereo transceiver that allows the
|
||||
processor to receive and transmit digital audio via a coaxial or
|
||||
fibre cable.
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rockchip,rk3066-spdif
|
||||
- const: rockchip,rk3228-spdif
|
||||
- const: rockchip,rk3328-spdif
|
||||
- const: rockchip,rk3366-spdif
|
||||
- const: rockchip,rk3368-spdif
|
||||
- const: rockchip,rk3399-spdif
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,rk3188-spdif
|
||||
- rockchip,rk3288-spdif
|
||||
- const: rockchip,rk3066-spdif
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: clock for SPDIF bus
|
||||
- description: clock for SPDIF controller
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
- const: hclk
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
|
||||
dma-names:
|
||||
const: tx
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
rockchip,grf:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
The phandle of the syscon node for the GRF register.
|
||||
Required property on RK3288.
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- dmas
|
||||
- dma-names
|
||||
- "#sound-dai-cells"
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3288-spdif
|
||||
|
||||
then:
|
||||
required:
|
||||
- rockchip,grf
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rk3188-cru.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
spdif: spdif@1011e000 {
|
||||
compatible = "rockchip,rk3188-spdif", "rockchip,rk3066-spdif";
|
||||
reg = <0x1011e000 0x2000>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_SPDIF>, <&cru HCLK_SPDIF>;
|
||||
clock-names = "mclk", "hclk";
|
||||
dmas = <&dmac1_s 8>;
|
||||
dma-names = "tx";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
@ -790,6 +790,9 @@ struct snd_soc_dai_link {
|
||||
const struct snd_soc_pcm_stream *params;
|
||||
unsigned int num_params;
|
||||
|
||||
struct snd_soc_dapm_widget *playback_widget;
|
||||
struct snd_soc_dapm_widget *capture_widget;
|
||||
|
||||
unsigned int dai_fmt; /* format to set on init */
|
||||
|
||||
enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
|
||||
|
@ -89,9 +89,9 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd)
|
||||
}
|
||||
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
|
||||
snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
|
||||
|
||||
ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
|
||||
if (ret) {
|
||||
|
@ -1903,7 +1903,6 @@ const struct soc_enum madera_isrc_fsh[] = {
|
||||
MADERA_ISRC4_FSH_SHIFT, 0xf,
|
||||
MADERA_RATE_ENUM_SIZE,
|
||||
madera_rate_text, madera_rate_val),
|
||||
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_isrc_fsh);
|
||||
|
||||
@ -1924,7 +1923,6 @@ const struct soc_enum madera_isrc_fsl[] = {
|
||||
MADERA_ISRC4_FSL_SHIFT, 0xf,
|
||||
MADERA_RATE_ENUM_SIZE,
|
||||
madera_rate_text, madera_rate_val),
|
||||
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_isrc_fsl);
|
||||
|
||||
@ -1938,7 +1936,6 @@ const struct soc_enum madera_asrc1_rate[] = {
|
||||
MADERA_ASYNC_RATE_ENUM_SIZE,
|
||||
madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
|
||||
madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
|
||||
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_asrc1_rate);
|
||||
|
||||
@ -1964,7 +1961,6 @@ const struct soc_enum madera_asrc2_rate[] = {
|
||||
MADERA_ASYNC_RATE_ENUM_SIZE,
|
||||
madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
|
||||
madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
|
||||
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(madera_asrc2_rate);
|
||||
|
||||
|
@ -820,8 +820,10 @@ static int tas571x_i2c_probe(struct i2c_client *client,
|
||||
|
||||
priv->regmap = devm_regmap_init(dev, NULL, client,
|
||||
priv->chip->regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
ret = PTR_ERR(priv->regmap);
|
||||
goto disable_regs;
|
||||
}
|
||||
|
||||
priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(priv->pdn_gpio)) {
|
||||
@ -845,7 +847,7 @@ static int tas571x_i2c_probe(struct i2c_client *client,
|
||||
|
||||
ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto disable_regs;
|
||||
|
||||
usleep_range(50000, 60000);
|
||||
|
||||
@ -861,12 +863,20 @@ static int tas571x_i2c_probe(struct i2c_client *client,
|
||||
*/
|
||||
ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto disable_regs;
|
||||
}
|
||||
|
||||
return devm_snd_soc_register_component(&client->dev,
|
||||
ret = devm_snd_soc_register_component(&client->dev,
|
||||
&priv->component_driver,
|
||||
&tas571x_dai, 1);
|
||||
if (ret)
|
||||
goto disable_regs;
|
||||
|
||||
return ret;
|
||||
|
||||
disable_regs:
|
||||
regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tas571x_i2c_remove(struct i2c_client *client)
|
||||
|
@ -394,6 +394,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
|
||||
.min_ch = 1,
|
||||
.max_ch = 1,
|
||||
.simple_ch_prep_sm = true,
|
||||
.read_only_wordlength = true,
|
||||
}, {
|
||||
/* COMP */
|
||||
.num = 2,
|
||||
@ -401,6 +402,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
|
||||
.min_ch = 1,
|
||||
.max_ch = 1,
|
||||
.simple_ch_prep_sm = true,
|
||||
.read_only_wordlength = true,
|
||||
}, {
|
||||
/* BOOST */
|
||||
.num = 3,
|
||||
@ -408,6 +410,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
|
||||
.min_ch = 1,
|
||||
.max_ch = 1,
|
||||
.simple_ch_prep_sm = true,
|
||||
.read_only_wordlength = true,
|
||||
}, {
|
||||
/* VISENSE */
|
||||
.num = 4,
|
||||
@ -415,6 +418,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
|
||||
.min_ch = 1,
|
||||
.max_ch = 1,
|
||||
.simple_ch_prep_sm = true,
|
||||
.read_only_wordlength = true,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -113,14 +113,6 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1308_2_adr[] = {
|
||||
{
|
||||
.adr = 0x000210025D130800,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &single_endpoint,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = {
|
||||
{
|
||||
.adr = 0x000110025D130800,
|
||||
|
@ -87,14 +87,6 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1308_2_adr[] = {
|
||||
{
|
||||
.adr = 0x000210025D130800,
|
||||
.num_endpoints = 1,
|
||||
.endpoints = &single_endpoint,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = {
|
||||
{
|
||||
.adr = 0x000110025D130800,
|
||||
|
@ -116,10 +116,8 @@ static int apq8096_platform_probe(struct platform_device *pdev)
|
||||
card->dev = dev;
|
||||
dev_set_drvdata(dev, card);
|
||||
ret = qcom_snd_parse_of(card);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error parsing OF data\n");
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
apq8096_add_be_ops(card);
|
||||
ret = snd_soc_register_card(card);
|
||||
|
@ -559,10 +559,8 @@ static int sdm845_snd_platform_probe(struct platform_device *pdev)
|
||||
card->dev = dev;
|
||||
dev_set_drvdata(dev, card);
|
||||
ret = qcom_snd_parse_of(card);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error parsing OF data\n");
|
||||
if (ret)
|
||||
goto parse_dt_fail;
|
||||
}
|
||||
|
||||
data->card = card;
|
||||
snd_soc_card_set_drvdata(card, data);
|
||||
|
@ -656,60 +656,6 @@ void s3c_i2sv2_cleanup(struct snd_soc_dai *dai,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(s3c_i2sv2_cleanup);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct s3c_i2sv2_info *i2s = to_info(dai);
|
||||
u32 iismod;
|
||||
|
||||
if (dai->active) {
|
||||
i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
|
||||
i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
|
||||
i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
|
||||
|
||||
/* some basic suspend checks */
|
||||
|
||||
iismod = readl(i2s->regs + S3C2412_IISMOD);
|
||||
|
||||
if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
|
||||
pr_warn("%s: RXDMA active?\n", __func__);
|
||||
|
||||
if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
|
||||
pr_warn("%s: TXDMA active?\n", __func__);
|
||||
|
||||
if (iismod & S3C2412_IISCON_IIS_ACTIVE)
|
||||
pr_warn("%s: IIS active\n", __func__);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct s3c_i2sv2_info *i2s = to_info(dai);
|
||||
|
||||
pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
|
||||
dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
|
||||
|
||||
if (dai->active) {
|
||||
writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
|
||||
writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
|
||||
writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
|
||||
|
||||
writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
|
||||
i2s->regs + S3C2412_IISFIC);
|
||||
|
||||
ndelay(250);
|
||||
writel(0x0, i2s->regs + S3C2412_IISFIC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define s3c2412_i2s_suspend NULL
|
||||
#define s3c2412_i2s_resume NULL
|
||||
#endif
|
||||
|
||||
int s3c_i2sv2_register_component(struct device *dev, int id,
|
||||
const struct snd_soc_component_driver *cmp_drv,
|
||||
struct snd_soc_dai_driver *dai_drv)
|
||||
@ -727,9 +673,6 @@ int s3c_i2sv2_register_component(struct device *dev, int id,
|
||||
if (!ops->delay)
|
||||
ops->delay = s3c2412_i2s_delay;
|
||||
|
||||
dai_drv->suspend = s3c2412_i2s_suspend;
|
||||
dai_drv->resume = s3c2412_i2s_resume;
|
||||
|
||||
return devm_snd_soc_register_component(dev, cmp_drv, dai_drv, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(s3c_i2sv2_register_component);
|
||||
|
@ -117,6 +117,60 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int s3c2412_i2s_suspend(struct snd_soc_component *component)
|
||||
{
|
||||
struct s3c_i2sv2_info *i2s = snd_soc_component_get_drvdata(component);
|
||||
u32 iismod;
|
||||
|
||||
if (component->active) {
|
||||
i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
|
||||
i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
|
||||
i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
|
||||
|
||||
/* some basic suspend checks */
|
||||
|
||||
iismod = readl(i2s->regs + S3C2412_IISMOD);
|
||||
|
||||
if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
|
||||
pr_warn("%s: RXDMA active?\n", __func__);
|
||||
|
||||
if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
|
||||
pr_warn("%s: TXDMA active?\n", __func__);
|
||||
|
||||
if (iismod & S3C2412_IISCON_IIS_ACTIVE)
|
||||
pr_warn("%s: IIS active\n", __func__);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c2412_i2s_resume(struct snd_soc_component *component)
|
||||
{
|
||||
struct s3c_i2sv2_info *i2s = snd_soc_component_get_drvdata(component);
|
||||
|
||||
pr_info("component_active %d, IISMOD %08x, IISCON %08x\n",
|
||||
component->active, i2s->suspend_iismod, i2s->suspend_iiscon);
|
||||
|
||||
if (component->active) {
|
||||
writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
|
||||
writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
|
||||
writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
|
||||
|
||||
writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
|
||||
i2s->regs + S3C2412_IISFIC);
|
||||
|
||||
ndelay(250);
|
||||
writel(0x0, i2s->regs + S3C2412_IISFIC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define s3c2412_i2s_suspend NULL
|
||||
#define s3c2412_i2s_resume NULL
|
||||
#endif
|
||||
|
||||
#define S3C2412_I2S_RATES \
|
||||
(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
|
||||
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
|
||||
@ -146,6 +200,8 @@ static struct snd_soc_dai_driver s3c2412_i2s_dai = {
|
||||
|
||||
static const struct snd_soc_component_driver s3c2412_i2s_component = {
|
||||
.name = "s3c2412-i2s",
|
||||
.suspend = s3c2412_i2s_suspend,
|
||||
.resume = s3c2412_i2s_resume,
|
||||
};
|
||||
|
||||
static int s3c2412_iis_dev_probe(struct platform_device *pdev)
|
||||
|
@ -4165,6 +4165,8 @@ snd_soc_dapm_new_dai(struct snd_soc_card *card,
|
||||
w = snd_soc_dapm_new_control_unlocked(&card->dapm, &template);
|
||||
if (IS_ERR(w)) {
|
||||
ret = PTR_ERR(w);
|
||||
dev_err(rtd->dev, "ASoC: Failed to create %s widget: %d\n",
|
||||
link_name, ret);
|
||||
goto outfree_kcontrol_news;
|
||||
}
|
||||
|
||||
@ -4283,52 +4285,58 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dapm_add_valid_dai_widget(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_soc_dai *codec_dai,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
static void dapm_connect_dai_routes(struct snd_soc_dapm_context *dapm,
|
||||
struct snd_soc_dai *src_dai,
|
||||
struct snd_soc_dapm_widget *src,
|
||||
struct snd_soc_dapm_widget *dai,
|
||||
struct snd_soc_dai *sink_dai,
|
||||
struct snd_soc_dapm_widget *sink)
|
||||
{
|
||||
struct snd_soc_dapm_widget *playback = NULL, *capture = NULL;
|
||||
struct snd_soc_dapm_widget *codec, *playback_cpu, *capture_cpu;
|
||||
dev_dbg(dapm->dev, "connected DAI link %s:%s -> %s:%s\n",
|
||||
src_dai->component->name, src->name,
|
||||
sink_dai->component->name, sink->name);
|
||||
|
||||
if (dai) {
|
||||
snd_soc_dapm_add_path(dapm, src, dai, NULL, NULL);
|
||||
src = dai;
|
||||
}
|
||||
|
||||
snd_soc_dapm_add_path(dapm, src, sink, NULL, NULL);
|
||||
}
|
||||
|
||||
static void dapm_connect_dai_pair(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd,
|
||||
struct snd_soc_dai *codec_dai,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct snd_soc_dai_link *dai_link = rtd->dai_link;
|
||||
struct snd_soc_dapm_widget *dai, *codec, *playback_cpu, *capture_cpu;
|
||||
struct snd_pcm_substream *substream;
|
||||
struct snd_pcm_str *streams = rtd->pcm->streams;
|
||||
|
||||
if (rtd->dai_link->params) {
|
||||
if (dai_link->params) {
|
||||
playback_cpu = cpu_dai->capture_widget;
|
||||
capture_cpu = cpu_dai->playback_widget;
|
||||
} else {
|
||||
playback = cpu_dai->playback_widget;
|
||||
capture = cpu_dai->capture_widget;
|
||||
playback_cpu = playback;
|
||||
capture_cpu = capture;
|
||||
playback_cpu = cpu_dai->playback_widget;
|
||||
capture_cpu = cpu_dai->capture_widget;
|
||||
}
|
||||
|
||||
/* connect BE DAI playback if widgets are valid */
|
||||
codec = codec_dai->playback_widget;
|
||||
|
||||
if (playback_cpu && codec) {
|
||||
if (!playback) {
|
||||
if (dai_link->params && !dai_link->playback_widget) {
|
||||
substream = streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
|
||||
playback = snd_soc_dapm_new_dai(card, substream,
|
||||
"playback");
|
||||
if (IS_ERR(playback)) {
|
||||
dev_err(rtd->dev,
|
||||
"ASoC: Failed to create DAI %s: %ld\n",
|
||||
codec_dai->name,
|
||||
PTR_ERR(playback));
|
||||
dai = snd_soc_dapm_new_dai(card, substream, "playback");
|
||||
if (IS_ERR(dai))
|
||||
goto capture;
|
||||
}
|
||||
|
||||
snd_soc_dapm_add_path(&card->dapm, playback_cpu,
|
||||
playback, NULL, NULL);
|
||||
dai_link->playback_widget = dai;
|
||||
}
|
||||
|
||||
dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
|
||||
cpu_dai->component->name, playback_cpu->name,
|
||||
codec_dai->component->name, codec->name);
|
||||
|
||||
snd_soc_dapm_add_path(&card->dapm, playback, codec,
|
||||
NULL, NULL);
|
||||
dapm_connect_dai_routes(&card->dapm, cpu_dai, playback_cpu,
|
||||
dai_link->playback_widget,
|
||||
codec_dai, codec);
|
||||
}
|
||||
|
||||
capture:
|
||||
@ -4336,52 +4344,20 @@ capture:
|
||||
codec = codec_dai->capture_widget;
|
||||
|
||||
if (codec && capture_cpu) {
|
||||
if (!capture) {
|
||||
if (dai_link->params && !dai_link->capture_widget) {
|
||||
substream = streams[SNDRV_PCM_STREAM_CAPTURE].substream;
|
||||
capture = snd_soc_dapm_new_dai(card, substream,
|
||||
"capture");
|
||||
if (IS_ERR(capture)) {
|
||||
dev_err(rtd->dev,
|
||||
"ASoC: Failed to create DAI %s: %ld\n",
|
||||
codec_dai->name,
|
||||
PTR_ERR(capture));
|
||||
dai = snd_soc_dapm_new_dai(card, substream, "capture");
|
||||
if (IS_ERR(dai))
|
||||
return;
|
||||
}
|
||||
|
||||
snd_soc_dapm_add_path(&card->dapm, capture,
|
||||
capture_cpu, NULL, NULL);
|
||||
dai_link->capture_widget = dai;
|
||||
}
|
||||
|
||||
dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
|
||||
codec_dai->component->name, codec->name,
|
||||
cpu_dai->component->name, capture_cpu->name);
|
||||
|
||||
snd_soc_dapm_add_path(&card->dapm, codec, capture,
|
||||
NULL, NULL);
|
||||
dapm_connect_dai_routes(&card->dapm, codec_dai, codec,
|
||||
dai_link->capture_widget,
|
||||
cpu_dai, capture_cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i;
|
||||
|
||||
if (rtd->num_cpus == 1) {
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai)
|
||||
dapm_add_valid_dai_widget(card, rtd, codec_dai,
|
||||
asoc_rtd_to_cpu(rtd, 0));
|
||||
} else if (rtd->num_codecs == rtd->num_cpus) {
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai)
|
||||
dapm_add_valid_dai_widget(card, rtd, codec_dai,
|
||||
asoc_rtd_to_cpu(rtd, i));
|
||||
} else {
|
||||
dev_err(card->dev,
|
||||
"N cpus to M codecs link is not supported yet\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
|
||||
int event)
|
||||
{
|
||||
@ -4422,6 +4398,8 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream,
|
||||
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
int i;
|
||||
|
||||
/* for each BE DAI link... */
|
||||
for_each_card_rtds(card, rtd) {
|
||||
@ -4432,7 +4410,18 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
|
||||
if (rtd->dai_link->dynamic)
|
||||
continue;
|
||||
|
||||
dapm_connect_dai_link_widgets(card, rtd);
|
||||
if (rtd->num_cpus == 1) {
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai)
|
||||
dapm_connect_dai_pair(card, rtd, codec_dai,
|
||||
asoc_rtd_to_cpu(rtd, 0));
|
||||
} else if (rtd->num_codecs == rtd->num_cpus) {
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai)
|
||||
dapm_connect_dai_pair(card, rtd, codec_dai,
|
||||
asoc_rtd_to_cpu(rtd, i));
|
||||
} else {
|
||||
dev_err(card->dev,
|
||||
"N cpus to M codecs link is not supported yet\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -894,7 +894,13 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
|
||||
}
|
||||
|
||||
/* create any TLV data */
|
||||
soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
|
||||
err = soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
|
||||
if (err < 0) {
|
||||
dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
|
||||
mc->hdr.name);
|
||||
kfree(sm);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* pass control to driver for optional further init */
|
||||
err = soc_tplg_init_kcontrol(tplg, &kc,
|
||||
@ -1118,6 +1124,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
|
||||
struct snd_soc_tplg_hdr *hdr)
|
||||
{
|
||||
struct snd_soc_tplg_ctl_hdr *control_hdr;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (tplg->pass != SOC_TPLG_PASS_MIXER) {
|
||||
@ -1146,25 +1153,30 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
|
||||
case SND_SOC_TPLG_CTL_RANGE:
|
||||
case SND_SOC_TPLG_DAPM_CTL_VOLSW:
|
||||
case SND_SOC_TPLG_DAPM_CTL_PIN:
|
||||
soc_tplg_dmixer_create(tplg, 1,
|
||||
le32_to_cpu(hdr->payload_size));
|
||||
ret = soc_tplg_dmixer_create(tplg, 1,
|
||||
le32_to_cpu(hdr->payload_size));
|
||||
break;
|
||||
case SND_SOC_TPLG_CTL_ENUM:
|
||||
case SND_SOC_TPLG_CTL_ENUM_VALUE:
|
||||
case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
|
||||
case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
|
||||
case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
|
||||
soc_tplg_denum_create(tplg, 1,
|
||||
le32_to_cpu(hdr->payload_size));
|
||||
ret = soc_tplg_denum_create(tplg, 1,
|
||||
le32_to_cpu(hdr->payload_size));
|
||||
break;
|
||||
case SND_SOC_TPLG_CTL_BYTES:
|
||||
soc_tplg_dbytes_create(tplg, 1,
|
||||
le32_to_cpu(hdr->payload_size));
|
||||
ret = soc_tplg_dbytes_create(tplg, 1,
|
||||
le32_to_cpu(hdr->payload_size));
|
||||
break;
|
||||
default:
|
||||
soc_bind_err(tplg, control_hdr, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ret < 0) {
|
||||
dev_err(tplg->dev, "ASoC: invalid control\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1272,7 +1284,9 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
|
||||
routes[i]->dobj.index = tplg->index;
|
||||
list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
|
||||
|
||||
soc_tplg_add_route(tplg, routes[i]);
|
||||
ret = soc_tplg_add_route(tplg, routes[i]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
/* add route, but keep going if some fail */
|
||||
snd_soc_dapm_add_routes(dapm, routes[i], 1);
|
||||
@ -1355,7 +1369,13 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
|
||||
}
|
||||
|
||||
/* create any TLV data */
|
||||
soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
|
||||
err = soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
|
||||
if (err < 0) {
|
||||
dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
|
||||
mc->hdr.name);
|
||||
kfree(sm);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* pass control to driver for optional further init */
|
||||
err = soc_tplg_init_kcontrol(tplg, &kc[i],
|
||||
@ -1766,10 +1786,13 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_stream_info(struct snd_soc_pcm_stream *stream,
|
||||
static int set_stream_info(struct snd_soc_pcm_stream *stream,
|
||||
struct snd_soc_tplg_stream_caps *caps)
|
||||
{
|
||||
stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
|
||||
if (!stream->stream_name)
|
||||
return -ENOMEM;
|
||||
|
||||
stream->channels_min = le32_to_cpu(caps->channels_min);
|
||||
stream->channels_max = le32_to_cpu(caps->channels_max);
|
||||
stream->rates = le32_to_cpu(caps->rates);
|
||||
@ -1777,6 +1800,8 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream,
|
||||
stream->rate_max = le32_to_cpu(caps->rate_max);
|
||||
stream->formats = le64_to_cpu(caps->formats);
|
||||
stream->sig_bits = le32_to_cpu(caps->sig_bits);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
|
||||
@ -1812,20 +1837,29 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
|
||||
if (dai_drv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (strlen(pcm->dai_name))
|
||||
if (strlen(pcm->dai_name)) {
|
||||
dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL);
|
||||
if (!dai_drv->name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
dai_drv->id = le32_to_cpu(pcm->dai_id);
|
||||
|
||||
if (pcm->playback) {
|
||||
stream = &dai_drv->playback;
|
||||
caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pcm->capture) {
|
||||
stream = &dai_drv->capture;
|
||||
caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pcm->compress)
|
||||
@ -1835,11 +1869,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
|
||||
ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
|
||||
kfree(dai_drv->playback.stream_name);
|
||||
kfree(dai_drv->capture.stream_name);
|
||||
kfree(dai_drv->name);
|
||||
kfree(dai_drv);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dai_drv->dobj.index = tplg->index;
|
||||
@ -1860,6 +1890,14 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(dai_drv->playback.stream_name);
|
||||
kfree(dai_drv->capture.stream_name);
|
||||
kfree(dai_drv->name);
|
||||
kfree(dai_drv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1916,11 +1954,20 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
|
||||
if (strlen(pcm->pcm_name)) {
|
||||
link->name = kstrdup(pcm->pcm_name, GFP_KERNEL);
|
||||
link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL);
|
||||
if (!link->name || !link->stream_name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
link->id = le32_to_cpu(pcm->pcm_id);
|
||||
|
||||
if (strlen(pcm->dai_name))
|
||||
if (strlen(pcm->dai_name)) {
|
||||
link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL);
|
||||
if (!link->cpus->dai_name) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
link->codecs->name = "snd-soc-dummy";
|
||||
link->codecs->dai_name = "snd-soc-dummy-dai";
|
||||
@ -2088,7 +2135,9 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
|
||||
_pcm = pcm;
|
||||
} else {
|
||||
abi_match = false;
|
||||
pcm_new_ver(tplg, pcm, &_pcm);
|
||||
ret = pcm_new_ver(tplg, pcm, &_pcm);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* create the FE DAIs and DAI links */
|
||||
@ -2436,13 +2485,17 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
|
||||
if (d->playback) {
|
||||
stream = &dai_drv->playback;
|
||||
caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (d->capture) {
|
||||
stream = &dai_drv->capture;
|
||||
caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE];
|
||||
set_stream_info(stream, caps);
|
||||
ret = set_stream_info(stream, caps);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (d->flag_mask)
|
||||
@ -2454,10 +2507,15 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
|
||||
ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai);
|
||||
if (ret < 0) {
|
||||
dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(dai_drv->playback.stream_name);
|
||||
kfree(dai_drv->capture.stream_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* load physical DAI elements */
|
||||
@ -2466,7 +2524,7 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
|
||||
{
|
||||
struct snd_soc_tplg_dai *dai;
|
||||
int count;
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
count = le32_to_cpu(hdr->count);
|
||||
|
||||
@ -2481,7 +2539,12 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
soc_tplg_dai_config(tplg, dai);
|
||||
ret = soc_tplg_dai_config(tplg, dai);
|
||||
if (ret < 0) {
|
||||
dev_err(tplg->dev, "ASoC: failed to configure DAI\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size));
|
||||
}
|
||||
|
||||
|
@ -837,7 +837,7 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
|
||||
cr1 = SAI_XCR1_DS_SET(SAI_DATASIZE_32);
|
||||
break;
|
||||
default:
|
||||
dev_err(cpu_dai->dev, "Data format not supported");
|
||||
dev_err(cpu_dai->dev, "Data format not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user